The FOREACH statement executes one or more statements for each element of an input set (which can be an array, list, or hash table). Within the FOREACH loop, you have access to a copy of the current element value and (optionally) the index or key for that value.
Note: Unlike other loop statements in IDL, FOREACH does not use a loop counter. It iterates through all of the items in an input set.
Syntax
FOREACH Element, Variable [, Index] DO Statement
or
FOREACH Element, Variable [, Index] DO BEGIN
statements
ENDFOREACH
If Variable is an array or list, then the optional Index is set to an integer corresponding to the current loop index. If Variable is a hash, then Index is set to the key corresponding to the current key-value pair.
Note: If Variable is undefined then a runtime error will be thrown.
Note: If Variable is !NULL, or is a scalar null object or scalar null pointer, then FOREACH will quietly return without doing any iterations. Note that this behavior will be different for a 1-element array of objects or pointers: In that case the FOREACH will iterate over the single element, even if it is a null object or null pointer.
Note: If Variable is a scalar then the FOREACH will iterate over the single element (unless as noted above it is a null object or pointer).
Examples
FOREACH with an Array or List
A simple FOREACH code example:
array = [1, 3, 5, 7, 9, 11, 13, 15]
FOREACH element, array DO PRINT, 'Value = ', element
This code sample produces the following output:
Value = 1
Value = 3
Value = 5
Value = 7
Value = 9
Value = 11
Value = 13
Value = 15
The same example, but also supplying the optional index argument:
array = [1, 3, 5, 7, 9, 11, 13, 15]
FOREACH element, array, index DO PRINT, 'Index ', index, ' Value = ', element
This code sample produces the following output:
Index 0 Value = 1
Index 1 Value = 3
Index 2 Value = 5
Index 3 Value = 7
Index 4 Value = 9
Index 5 Value = 11
Index 6 Value = 13
Index 7 Value = 15
The next example uses the block structure (instead of a single statement):
PRO testForeach
list = LIST(77.97, 'Galactic', [2, 7, 1, 8, 2])
FOREACH element, list DO BEGIN
PRINT, 'Value = ', element
ENDFOREACH
END
After compiling and running the procedure, it produces the following output:
Value = 77.9700
Value = Galactic
Value = 2 7 1 8 2
FOREACH where Variable is an Expression
In a FOREACH statement, Variable can be an expression as well as a literal. In this example, we create a two-dimensional array and use an expression for Variable to print out the third column elements.
The 3x3 array elements are:
0 1 2
3 4 5
6 7 8
arr = INDGEN(3,3)
FOREACH element, arr[2,*] DO PRINT, element
IDL prints:
2
5
8
FOREACH with a HASH Table
In this example, we create a hash and loop through all of the key-value pairs.
planets = HASH('Mercury', 0.3e24, 'Venus', 5e24, $
'Earth', 6e24, 'Mars', 0.65e24, 'Jupiter', 1900e24, $
'Saturn', 570e24, 'Uranus', 87e24, 'Neptune', 100e24, $
'Pluto', 0.7e24)
FOREACH mass, planets, key DO PRINT, key, mass
IDL prints:
Mercury 3.00000e+023
Venus 5.00000e+024
Earth 6.00000e+024
Neptune 1.00000e+026
Saturn 5.70000e+026
Mars 6.50000e+023
Uranus 8.70000e+025
Pluto 7.00000e+023
Jupiter 1.90000e+027
Notice that the order in which the keys are returned is arbitrary for a hash table.
Note: While iterating through a list, hash, ordered hash, or dictionary, avoid adding or removing elements. If the set is changed during the FOREACH, the behavior is undefined.
Modifying FOREACH Elements
Each element within the FOREACH loop is a copy of the data value within the set. If you change the element value, it may or may not change the actual stored data value, depending upon the underlying data structure.
For example, if you have an IDL array of numbers or strings, or you have a list or hash containing only scalars or arrays, then changing the element value will have no effect:
arr = [1,2,3,4,5]
foreach a, arr do a = 99
lst = list('str1', 'str2', 'str3')
foreach item, lst do item = 'other string'
lst = list([1,2,3], [4,5,6])
foreach item, lst do item[1] = 99 h = hash('red', [255,0,0], 'green', [0,255,0], 'blue', [0,0,255])
foreach h1, h do h1[0] = 99
However, if you have a nested list or hash, then even though the element is a copy of the reference, that reference will still point to the original underlying element (in other words, it is a shallow copy). For example:
lst = list(list(1,2), list(3,4))
foreach item, lst do item[1] = 99
print, lst.toString()
IDL prints:
[[1,99],[3,99]]
Another example involving a hash:
h = hash('red', list(255,0,0), 'green', list(0,255,0), 'blue', list(0,0,255))
foreach h1, h do h1[0] = 99
print, h.toString()
IDL prints:
{red:[99,0,0],green:[99,255,0],blue:[99,0,255]}
Therefore, when modifying the elements within the FOREACH, you should be aware of any side effects to your original variable.
Version History
See Also
BEGIN...END,
BREAK, CASE,
CONTINUE, FOR,
GOTO, HASH,
IF...THEN...ELSE, LIST,
REPEAT...UNTIL,
SWITCH,
WHILE...DO
IDL Programming