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.


FOREACH Element, Variable [, Index] DO Statement


FOREACH Element, Variable [, Index] DO BEGIN



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).


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

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:


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 ; has no effect
lst = list('str1', 'str2', 'str3')
foreach item, lst do item = 'other string' ; has no effect
lst = list([1,2,3], [4,5,6])
foreach item, lst do item[1] = 99 ; has no effect
h = hash('red', [255,0,0], 'green', [0,255,0], 'blue', [0,0,255])
foreach h1, h do h1[0] = 99 ; has no effect

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:


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:


Therefore, when modifying the elements within the FOREACH, you should be aware of any side effects to your original variable.

Version History



See Also


IDL Programming