items: (Any Type Array) An array or DataSubset containing the items to iterate over.
expression: (Any Type) An expression that will be evaluated for each item. The following function variables are available when configuring this input:
Any Type Array
The result of each expression evaluation is appended to the returned list in the same order as the corresponding item in items.
a!forEach(items: {100, 200, 300}, expression: fv!item + 1)
returns {101, 201, 301}
The expression parameter can be configured with any valid expression, including any number of rules, functions, constants, etc.
a!forEach(items: {1, null, 3}, expression: if(isnull(fv!item), "No Value", "Value: " & fv!item))
returns {"Value: 1", "No Value", "Value: 3"}
Multiple function variables can be used in the same expression.
1
2
3
4
a!forEach(
items: {"apple", "pear", "banana"},
expression: "Word " & fv!index & " is length: " & len(fv!item)
)
returns: {"Word 1 is length: 5", "Word 2 is length: 4", "Word 3 is length: 6"}
The same variable can also be used multiple times.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
concat(
a!forEach(
items: {"the", "variables", "fv!isFirst", "and", "fv!isLast", "are", "helpful"},
expression: concat(
if(
fv!isFirst,
proper(fv!item),
fv!item
),
if(
fv!isLast,
"!",
" "
)
)
)
)
returns: "The variables fv!isFirst and fv!isLast are helpful!"
When items is null or an empty list, a!forEach()
returns an empty list of the same type as items. It does not evaluate the expression in these cases.
a!forEach(items: null, expression: length(fv!item))
returns {}
When passed a single non-null value that is not a DataSubset, a!forEach() evaluates the expression once for that value and returns the result in a single-item list.
a!forEach(items: 3, expression: fv!item + 1
returns {4}
When items is passed a DataSubset:
a!forEach()
iterates through the DataSubset's data field.a!forEach(items: a!dataSubset(data: {1, 2, 3 }), expression: fv!item + 2)
returns {3, 4, 5}
In the interface, the expression parameter can contain interface components, a!localVariables() variables, and load() variables. To edit the current array item, interface components should save values into fv!item
instead of indexing back into the original array so that a!forEach()
can keep local variables associated with the correct rows.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
a!localVariables(
local!names: {"Alice", "Bob", "Carol"},
a!forEach(
items: local!names,
expression: a!localVariables(
local!modified,
a!textField(
instructions: if(local!modified, "Modified!", ""),
value: fv!item,
saveInto: {
fv!item,
a!save(local!modified, true)
}
)
)
)
)
If the original array needs to be modified without writing to fv!item
, either because it is being changed outside the a!forEach()
loop or because a loop iteration is modifying an item besides the current one, then use a DataSubset with identifiers to make sure local variables are associated with the correct rows.
If the result of any expression is an array, a!forEach()
returns a two-dimensional array. Two-dimensional arrays can be useful when processing data, but not all functions support them. Two-dimensional arrays are auto-flattened into one-dimensional arrays upon being stored in a process variable, node input, typed rule input, or custom data type field. Local variables, however, can store the two-dimensional array without flattening them.
a!forEach(items: {1, 2, 3}, expression: enumerate(fv!item)))
returns a 3 item list consisting of {0}
, {0, 1}
, and {0, 1, 2}
You can use a!flatten() on the result of a!forEach()
to convert to a one-dimensional array.
If a two-dimensional array is passed to the items parameter, a!forEach()
evaluates the expression once for each item in the outer array. In these cases fv!item
may be an array.
a!forEach(items: merge({1,2}, {10,20}), expression: fv!item[1] + fv!item[2])
returns {11, 22}
fv!item
is always cast to its runtime type and will not appear to be Any Type even if that is what was passed in to items.
a!forEach(items: {1, "hello"}, expression: typename(typeof(fv!item)))
returns {"Number (Integer)", "Text"}
If you need to nest an a!forEach()
inside another a!forEach()
and want to refer to the outer fv!item
, you can either put it in a local variable before calling the second a!forEach()
or put the inner call in a separate rule and pass in fv!item
via a rule input. For example:
1
2
3
4
5
6
7
8
9
10
a!forEach(
items: {"January", "February", "March"},
expression: a!localVariables(
local!month: fv!item,
a!forEach(
items: {1, 15},
expression: local!month & " " & fv!item
)
)
)
The above expression returns a three item list containing {"January 1", "January 15"}
, {"February 1", "February 15"}
, and {"March 1", "March 15"}
See also: Arrays in Expressions, Looping Recipes