# Working with Lists

### Working with Lists

Now that we've established what a list is, let's talk about operations we can perform on it. Imagine a list as a deck of playing cards. A deck is the list and each playing card represents an item.

![cards](/files/9DAyXBFWfn3SBmXZFCCU)

> Photo by [Christian Gidlöf](https://commons.wikimedia.org/wiki/File:Playing_cards_modified.jpg)

### Query

What **queries** can we make from the list? This accesses existing properties.

* Number of cards in the deck? 52.
* Number of suits? 4.
* Material? Paper.
* Length? 3.5" or 89mm.
* Width? 2.5" or 64mm.

### Action

What **actions** can we perform on the list? This changes the list based on a given operation.

* We can shuffle the deck.
* We can sort the deck by value.
* We can sort the deck by suit.
* We can split the deck.
* We can partition the deck by dealing out individual hands.
* We can select a specific card in the deck.

All of the operations listed above have analogous Dynamo nodes for working with lists of generic data. The lessons below will demonstrate some of the fundamental operations we can perform on lists.

## **Exercise**

### **List Operations**

> Download the example file by clicking on the link below.
>
> A full list of example files can be found in the Appendix.

{% file src="/files/O14m6AeuQivT3d1PoQs0" %}

The image below is the base graph which we are drawing lines between two circles to represent basic list operations. We'll explore how to manage data within a list and demonstrate the visual results through the list actions below.

![](/files/zvUOPXBgj5NKZiAIPjrg)

> 1. Begin with a **Code Block** with a value of `500;`
> 2. Plug into the x input of a **Point.ByCoordinates** node.
> 3. Plug the node from the previous step into the origin input of a **Plane.ByOriginNormal** node.
> 4. Using a **Circle.ByPlaneRadius** node, plug the node from the previous step into the plane input.
> 5. Using **Code Block**, designate a value of `50;` for the radius. This is the first circle we'll create.
> 6. With a **Geometry.Translate** node, move the circle up 100 units in the Z direction.
> 7. With a **Code Block** node, define a range of ten numbers between 0 and 1 with this line of code: `0..1..#10;`
> 8. Plug the code block from the previous step into the *param* input of two **Curve.PointAtParameter** nodes. Plug **Circle.ByPlaneRadius** into the curve input of the top node, and **Geometry.Translate** into the curve input of the node beneath it.
> 9. Using a **Line.ByStartPointEndPoint**, connect the two **Curve.PointAtParameter** nodes.

### List.Count

> Download the example file by clicking on the link below.
>
> A full list of example files can be found in the Appendix.

{% file src="/files/P0HnejxQX6QnTIe0YT7Z" %}

The *List.Count* node is straightforward: it counts the number of values in a list and returns that number. This node gets more nuanced as we work with lists of lists, but we'll demonstrate that in the coming sections.

![Count](/files/P4Do6vL6xdjqgdynkyCQ)

> 1. The **List.Count** node returns the number of lines in the **Line.ByStartPointEndPoint** node. The value is 10 in this case, which agrees with the number of points created from the original **Code Block** node.

### List.GetItemAtIndex

> Download the example file by clicking on the link below.
>
> A full list of example files can be found in the Appendix.

{% file src="/files/BSn41f389Ly7UZ54ZEAB" %}

**List.GetItemAtIndex** is a fundamental way to query an item in the list.

![Exercise](/files/zvQEAV6k8iPiMk84ovqR)

> 1. First, Right click on **Line.ByStartPointEndPoint** node to switch off its preview.
> 2. Using the **List.GetItemAtIndex** node, we are selecting index *"0"*, or the first item in the list of lines.

Change slider value between 0 and 9 to select different item using **List.GetItemAtIndex**.

![](/files/oOaDpkz02t1ZZCNzrCAV)

### List.Reverse

> Download the example file by clicking on the link below.
>
> A full list of example files can be found in the Appendix.

{% file src="/files/F5f9ck1FY0nAet6Rq1Hv" %}

*List.Reverse* reverses the order of all of the items in a list.

![Exercise](/files/8nftB5AddqItkl1FZ9HC)

> 1. To properly visualize the reversed list of lines, create more lines by changing the **Code Block** to `0..1..#50;`
> 2. Duplicate the **Line.ByStartPointEndPoint** node, insert a List.Reverse node in between **Curve.PointAtParameter** and the second **Line.ByStartPointEndPoint**
> 3. Use **Watch3D** nodes to preview two different results. The first one shows the result without a reversed list. The lines connect vertically to neighboring points. The reversed list, however, will connect all of the points to the opposing order in the other list.

### List.ShiftIndices <a href="#listshiftindices" id="listshiftindices"></a>

> Download the example file by clicking on the link below.
>
> A full list of example files can be found in the Appendix.

{% file src="/files/Tg7vNBjBMDm3KPpVTq8h" %}

**List.ShiftIndices** is a good tool for creating twists or helical patterns, or any other similar data manipulation. This node shifts the items in a list a given number of indices.

![Exercise](/files/DORun6VZvTjLoLs3yZOj)

> 1. In the same process as the reverse list, insert a **List.ShiftIndices** into the **Curve.PointAtParameter** and **Line.ByStartPointEndPoint**.
> 2. Using a **Code Block**, designated a value of "1" to shift the list one index.
> 3. Notice that the change is subtle, but all of the lines in the lower **Watch3D** node have shifted one index when connecting to the other set of points.

By changing to **Code Block** to a larger value, *"30"* for example, we notice a significant difference in the diagonal lines. The shift is working like a camera's iris in this case, creating a twist in the original cylindrical form.

![](/files/oic5NFpeAqUXabRff6J7)

### List.FilterByBooleanMask <a href="#listfilterbybooleanmask" id="listfilterbybooleanmask"></a>

> Download the example file by clicking on the link below.
>
> A full list of example files can be found in the Appendix.

{% file src="/files/YpbMe6BHaFdA2qkAezB5" %}

![](/files/vx4bzthI3uzeaC9wDs4R)

**List.FilterByBooleanMask** will remove certain items based on a list of booleans, or values reading "true" or "false".

![Exercise](/files/kdF8WPhM042x45LNgdBL)

In order to create a list of values reading "true" or "false", we need to a little more work...

> 1. Using a **Code Block**, define an expression with the syntax: `0..List.Count(list);`. Connect the **Curve.PointAtParameter** node to the *list* input. We'll walk through this setup more in the code block chapter, but the line of code in this case is giving us a list representing each index of the **Curve.PointAtParameter** node.
> 2. Using a ***%***\*\* (modulus)\*\* node, connect the output of the *code block* into the *x* input, and a value of *4* into the *y* input. This will give us the remainder when dividing the list of indices by 4. Modulus is a really helpful node for pattern creation. All values will read as the possible remainders of 4: 0, 1, 2, 3.
> 3. From the ***%***\*\* (modulus)\*\* node, we know that a value of 0 means that the index is divisible by 4 (0,4,8,etc...). By using a **==** node, we can test for the divisibility by testing it against a value of *"0"*.
> 4. The **Watch** node reveals just this: we have a true/false pattern which reads: *true,false,false,false...*.
> 5. Using this true/false pattern, connect to the mask input of two **List.FilterByBooleanMask** nodes.
> 6. Connect the **Curve.PointAtParameter** node into each list input for the **List.FilterByBooleanMask**.
> 7. The output of **Filter.ByBooleanMask** reads *"in"* and *"out"*. *"In"* represents values which had a mask value of *"true"* while *"out"* represents values which had a value of *"false"*. By plugging the *"in"* outputs into the *startPoint* and *endPoint* inputs of a **Line.ByStartPointEndPoint** node, we've created a filtered list of lines.
> 8. The **Watch3D** node reveals that we have fewer lines than points. We've selected only 25% of the nodes by filtering only the true values!


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://primer2.dynamobim.org/5_essential_nodes_and_concepts/5-4_designing-with-lists/2-working-with-lists.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
