7
$\begingroup$

What are some different syntax choices for loops that iterate over arrays? Of course, there is the common for loop:

for (int i = 0; i < 8; ++i) {
    myArr[i]
}

But this isn't the only option. What are some others?

$\endgroup$

10 Answers 10

11
$\begingroup$

Functional languages may have a higher-order function (not a list method!) which takes a function/lambda/operator and one (or more!) arrays, and iterates over them. E.g. APL and BQN have Each (¨) which, together with Take () allows us to take various prefixes from a corresponding number of strings:

      3 1 4↑¨'Hello' 'There' 'World'
┌───┬─┬────┐
│Hel│T│Worl│
└───┴─┴────┘

We can of course also use it with a single list, here with Reverse ():

      ⌽¨'Hello' 'There' 'World'
┌─────┬─────┬─────┐
│olleH│erehT│dlroW│
└─────┴─────┴─────┘

Note that ¨ is not something built into the lists, as we can assign the result of ¨ combining with an operation:

      ReverseEach←⌽¨
      ReverseEach 'Hello' 'There' 'World'
┌─────┬─────┬─────┐
│olleH│erehT│dlroW│
└─────┴─────┴─────┘
$\endgroup$
9
$\begingroup$

For each function

Some languages have a ‘forEach‘ function on their lists that takes a list and a lambda, and applies that lambda to each item. For example, Kotlin:

list.forEach { item -> 
    println(item) 
}
$\endgroup$
1
  • $\begingroup$ This also exists in JavaScript $\endgroup$
    – Jacob
    Commented May 19, 2023 at 18:28
9
$\begingroup$

for-in

This is the approach taken by Swift and Python:

for el in arr {
  print(el)
}

JS does something similar, but for historical reasons it uses of instead:

for (const el of arr)
  console.log(el);
$\endgroup$
5
  • 1
    $\begingroup$ It's confusing in JS because in actually loops over the keys $\endgroup$
    – naffetS
    Commented May 19, 2023 at 17:42
  • 2
    $\begingroup$ PHP uses foreach ($arr as $el), which is backwards $\endgroup$
    – naffetS
    Commented May 19, 2023 at 17:44
  • $\begingroup$ PHP's syntax should probably be its own answer, then. $\endgroup$
    – Bbrk24
    Commented May 19, 2023 at 17:45
  • $\begingroup$ JS for...of uses [Symbol.iterator] as the iterator too $\endgroup$
    – Hydroper
    Commented Jun 1, 2023 at 11:54
  • $\begingroup$ And Rust... and Kotlin... $\endgroup$
    – Seggan
    Commented Jun 12, 2023 at 13:03
6
$\begingroup$

Functor fmap

For repetitive (but not only) tasks over a structure like an Array, I like the Functional Programming point of view: map/fmap syntax

The goal of it is pretty similar to foreach in imperative languages

If you happen to have any structure that is a candidate for being a Functor (there are only a few features to respect for this), and lists / arrays are Functors, in Haskell, you can do this:

fmap myFunction myArray

Once accustomed to it, for me it is difficult to want to use something else. myFunction can of course be a short lambda definition

fmap (\x -> x+1) myArrayOfXs

In case you have a computation that is more than reading or doing simple stuffs, you can also use the more elaborated mapM, but then we enter the realm of Monads. I just mention it here.

And finally, there's Traversable typeclass/interface to iterate over Traversable containers: not only can you iterate and have behaviour during the iterationm, but you can even create a structure issuing from the iteration.

$\endgroup$
4
$\begingroup$

Java for each

for (int item : myArr) {
    System.out.println(item);
}

This style is easier, as we don't need to keep track of an iterator variable (like i), and instead we can work directly with item instead. It does come with a tradeoff when item is a copy of an item in myArr, as we can't easily modify the original array

for (int item : myArr) {
    // this changes item, but not the original item in myArr
    item = 0;
}
$\endgroup$
4
  • $\begingroup$ "It does come with a tradeoff when item is a copy of an item in myArr, as we can't easily modify the original array" that's true in Java but does not have to be true in general: item might be a reference to the array slot, thus item = 0 could directly manipulate the array. I don't know of any language that does this with a for-each but it still could be done. $\endgroup$
    – VLAZ
    Commented May 19, 2023 at 18:15
  • $\begingroup$ @VLAZ-onstrike- I think rust can do that with iter_mut $\endgroup$
    – Seggan
    Commented Jun 12, 2023 at 13:04
  • $\begingroup$ C++ has that, for (int& item : arr). In fact, I've seen at least as much "borrowing" for (const auto& item : arr) as I have copying for (auto item : arr). $\endgroup$
    – Bbrk24
    Commented Jun 12, 2023 at 13:07
  • $\begingroup$ @VLAZ-onstrike- PHP does that in foreach ($arr as &$item) {}: the & indicates using a reference. You do need to unset($item) at the end of the loop or you get weirdness. $\endgroup$
    – TRiG
    Commented Jul 3, 2023 at 20:15
4
$\begingroup$

Backwards foreach

PHP uses this:

foreach ($arr as $el) {
  ...
}

I think there might also be a language that uses something like foreach (arr => el), but I don't remember what.

$\endgroup$
1
  • $\begingroup$ You can also use ($arr as $key=>$value) for associative arrays $\endgroup$
    – mousetail
    Commented May 19, 2023 at 17:55
4
$\begingroup$

for range

https://go.dev/tour/moretypes/16

for index, value := range data {
    fmt.Printf("2**%d = %d\n", index, value)
}
$\endgroup$
3
$\begingroup$

Iterating over multiple arrays together, and in fixed-size chunks

Below are quoted from the Tcl man page. Note that in Tcl, arrays are read into a list in a single level by the format {key value key value ...} that odd elements are keys, and even elements are values, which is probably why it would be helpful to iterate in chunks. The part about iterating over multiple arrays would be much more useful in other languages. It also has a variant version lmap which works like foreach but also collects the result. {} denotes an empty string.

The following loop uses i and j as loop variables to iterate over pairs of elements of a single list.

set x {}
foreach {i j} {a b c d e f} {
    lappend x $j $i
}
# The value of x is "b a d c f e"
# There are 3 iterations of the loop.

The next loop uses i and j to iterate over two lists in parallel.

set x {}
foreach i {a b c} j {d e f g} {
    lappend x $i $j
}
# The value of x is "a d b e c f {} g"
# There are 4 iterations of the loop.

The two forms are combined in the following example.

set x {}
foreach i {a b c} {j k} {d e f g} {
    lappend x $i $j $k
}
# The value of x is "a d e b f g c {} {}"
# There are 3 iterations of the loop.
$\endgroup$
2
$\begingroup$

C# foreach

foreach (int number in Numbers) {
    ...
}
$\endgroup$
2
  • $\begingroup$ Isn't this essentially the same as Java? $\endgroup$
    – Adám
    Commented Jun 1, 2023 at 13:57
  • $\begingroup$ @Adám - no, as it uses an additional keyword in rather than punctuation :. There are pros and cons for the two choices, so it's worth listing both. $\endgroup$
    – occipita
    Commented Jul 30, 2023 at 16:43
2
$\begingroup$

Generator Functions

for key, value in pairs(table) do
    print(value)
end

Lua doesn't support table iteration as a keyword directly, instead relying on generators to do the heavy lifting.

This is notably different from languages like Python and C# in that the for keyword does not support directly iterating over any object, only generator functions.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .