ForEach¶
Apply a function or loop body to each item in a collection or iterator.
The loop body (the collection of nodes you wish to run repeatedly) must begin with a Placeholder node that receives the item, and end with the ForEach node. The ForEach node will invoke the loop body for each item in the iterable input port, and collect the results into a list, dictionary, or flatten them into a single container of the same type as the type of the item the ForEach node receives from the end of the loop body. (Use the collect property to change this behavior.) By default the ForEach node returns only the last result from the loop body. By default, nodes in the loop body do not carry over their internal across iterations of the ForEach node; this behavior can be changed by setting the stateless property to false. (For example, if you want to use PathIterator as an iterator inside a ForEach loop, you would want to configure ForEach to carry over the PathIterator's state by setting stateless to false.) You can use a Continue node in the loop body to skip the current item and proceed to the next item in the iterable, and the Break node to terminate the loop early. If items are being collected (based on the setting of the collect` property), this will truncate the collection at the point where the loop was terminated. If the iterable is an iterator node, you can wire the iterator node'sthisport into theiterableport of the ForEach node. The iterator node will be invoked for each repetition of the loop, pass the next item to the ForEach loop. (See the PathIterator and EnumerateIterator node documentation.) The variable passed by ForEach to Placeholder is by default nameditem, but can be renamed by changing thebody(item parameter) property. (If using a ForEach node in a python script, change the node'sbody__signature=constructor argument.) Note that if you rename item to some other name, you also need to change theslotname(name) in the Placeholder node to match. If the loop body does not use the iterable item that is passed to the Placeholder node, you can instead wire the Placeholder node'supdateport into theupdateport of the first node in the loop body in order to process the loop body without passing any value to it. The ForEach node can be used as a list or dictionary comprehension (and other types of comprehensions) by using thelist,dict, etc options in thecollectproperty. In this case the choice ofcollectdetermines the output data type, which need not be the same as the iterable that is being iterated over. It is also possible to use the ForEach node to flatten a nested collection, by using theflattenoption incollect``. This is is most useful when you want to implement a nested for loop (with multiple ForEach nodes) but want to collect the final results into a single flat container. In this case you choose flatten in the outer loop(s), and select the desired container type in the inner(most) loop. Note that flatten, while it can handle packets and arrays implements a simple default rule; for more complex cases you are advised to instead collect results into a list, and then concatenate the items yourself using whatever logic you need.
More Info...
Version 1.0.1
Ports/Properties¶
body¶
Graph to apply (loop body).
- verbose name: Body
- default value: None
- port type: GraphPort
- value type: Graph
body__signature¶
The list of loop variables received by the loop body. In a "For Each" loop, the loop body depends on only a single loop variable, namely the current item from the wired-in iterable. Consequently, your loop body should contain a single Placeholder node whose slotname must match the name listed here (e.g., item, but you can also choose a different name). Then, anything downstream of (i.e., depending on the value of) that Placeholder will constitute your loop body. The final output node of your loop body is then wired into the "body" input port of the loop node. In graphical UIs, the edge will be drawn in dotted style to indicate that the preceding graph itself is given to the loop node as the loop body (which will then execute it zero or more times), which is in contrast to a regular (solid) edge that indices normal data flow wherein first the preceding node runs, and then its output is passed to the subsequent node. The For Each node will then return a collection (see collect setting) of the values received from the final node on each iteration.
- verbose name: Body [Item Parameter]
- default value: (item)
- port type: Port
- value type: object (can be None)
iterable¶
Data to iterate over.
- verbose name: Iterable
- default value: None
- port type: DataPort
- value type: object (can be None)
- data direction: IN
result¶
ForEach result.
- verbose name: Result
- default value: None
- port type: DataPort
- value type: object (can be None)
- data direction: OUT
collect¶
Collect results into a list, dictionary, graph, packet, array or flatten the results into a single container of the same type emitted by the function. For graphs, a mix of nodes and edges may be emitted, and the resulting graph will have only those edges for which both endpoint nodes were also emitted separately (i.e., emitting an edge will not implicitly add its endpoint nodes). If 'last', only the last result is returned (as in Repeat). When applied to numeric arrays, the 'flatten' option concatenates the arrays along their existing first axis while the 'array' option stacks them along a new first axis. Packet and Graph are analogous to dict and list options, in that they are comprehensions that allow the user to itemize the constituents of these data structures (for packets, each is a 2-element list of [chunkname, Chunk] and for Graph each is a nodes and/or an edges). The dict-of-lists option is convenient when the loop body returns a list of dictionaries, and you wish to collect the results as a dictionary of lists; this can be a useful pattern for loop bodies with multiple return values, where the return values are wired into a Create Dictionary node and that dictionary is returned as the loop body result. The loop itself will then return a dictionary that has a list of items for each key.
- verbose name: Collect
- default value: list
- port type: EnumPort
- value type: str (can be None)
stateless¶
If True, then the loop body will not carry over its previous state across iterations. This can be used to ensure perfect isolation between iterations. In contrast, the option should be disabled if you wish your loop body nodes to retain prior state across loop iterations; an example is if you use an iterator node (separate from the loop's wired-in iterable) inside the loop body.
- verbose name: Stateless
- default value: True
- port type: BoolPort
- value type: bool (can be None)
compile¶
Whether and how to compile the loop body for more efficient execution. Off is the recommended default for anything except for the most performance-critical computations consisting of mainly math operations, possibly with some data reformatting. The 'jax' option will compile the loop to run on the jax backend; this comes with a series of limitations -- all nodes in the body have to work with jax data types (numeric values only) and operations, and break/continue nodes cannot be used. Auto will only compile the loop if it occurs in a context where compilation is necessary, for example inside a model passed to nodes such as DeepLearning, ConvexModel, or one of the Inference nodes.
- verbose name: Compile
- default value: off
- port type: EnumPort
- value type: str (can be None)
set_breakpoint¶
Set a breakpoint on this node. If this is enabled, your debugger (if one is attached) will trigger a breakpoint.
- verbose name: Set Breakpoint (Debug Only)
- default value: False
- port type: BoolPort
- value type: bool (can be None)
metadata¶
User-definable meta-data associated with the node. Usually reserved for technical purposes.
- verbose name: Metadata
- default value: {}
- port type: DictPort
- value type: dict (can be None)