0
$\begingroup$

In order to avoid a deep set of nested For loops, I came up with this method to do it with one For loop. The range of each level's For loop counting variable k1, k2, k3,... is 0 to b, and n is the number of nestings that I am replacing with one level. The advantage is for when n is a very large number. The disadvantage is lack of flexibility on the range of each counting variable.

Here is an example for n = 3 and b = 7:

b = 7; n = 3;
For[k = b^3, k < b^4, k++,   
    klist = RealDigits[k, b][[1]]; 
    k1= klist[[2]];
    k2 = klist[[3]];
    k3 = klist[[4]];
 (*  the rest of the code is here... *) ]

Does anyone know of other ways to flatten nested For loops?

$\endgroup$
  • 1
    $\begingroup$ What does $n$ have to do with anything? $\endgroup$ – David G. Stork Aug 15 '18 at 19:40
  • $\begingroup$ A simpler way to nest loops is to use Do or Table, both of which accept multiple iterators. $\endgroup$ – bill s Aug 15 '18 at 19:40
  • $\begingroup$ In the example it should have been k = b^n, not k = b^3. $\endgroup$ – user5922 Aug 15 '18 at 21:13
  • $\begingroup$ For the second comment, can you give an example of a Do or Table with multiple iterators? $\endgroup$ – user5922 Aug 15 '18 at 21:15
  • $\begingroup$ user5922, you can ping other users with @ just like @bills. $\endgroup$ – Henrik Schumacher Aug 15 '18 at 21:35
1
$\begingroup$

Not an answer but a longer comment.

It really depends on what (* the rest of the code is here... *) is. Many linear algebraic operations can be applied entirely without For constructs via vectorization (for arbitrary depth).

Anyways, For is not a first-class member of Mathematica. It is there only for compatibility reasons. (Valued by the many question about For on this site, it was one of the worst design decisions to include it, IMHO.) Mathematica just works differently. See also Why should I avoid the For loop in Mathematica?

Usually, what you want to use is indeed Do or Table. Do and Table are able to compile their body in certain circumstance which will grant an enormous performance boost. Plus the iterator in Do and Table is scoped which prevents a lot of tedious debugging.

Nonlinear operations can be also "looped" with the help of Map and depth specifications. If you really need to access the indices, MapIndexed is your friend: Write a function f that takes entries of a pre-existing array and its position indices as input and use something as follows:

data = Outer[List, Array[a, 2], Array[b, 3], Array[c, 4]];
MapIndexed[{X, i} \[Function] f[X, i], data, {3}]

Execute this in a fresh kernel to get an impression of what is happening there.

Side remark

For-loops are actually also not first-class members in C. Because of the flexibility on what you can do with the iterator in the body of a for-loop in C, they are actually very inefficient (compared to Fortran which is more restrictive in that respect). Runtime efficiency is only obtained because the compiler "optimizes away" most for-loops. (In Mathematica lingo, the compiler replaces For-loops by Do-loops or even by vectorization.)

$\endgroup$
1
$\begingroup$

One way to approach this is to use the form of the Do which in simplest form looks like this:

Do[Print[i], {i, {1, 2, 3}}]

The iterator can be of any dimension. So for a 2D example:

iters = {{1, 2}, {2, 3}, {4, 5}};
Do[Print[Total[i]], {i, iters}]

So this iterates with i equal to each of the three entries in the list iters. Similarly,

iters = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
Do[Print[Total[i]], {i, iters}]

this will iterate over all the elements of iters. The Print statement can be replaced by any function (or collection of functions) as long as they can take the vector i as input.

This changes the problem from how to use For (or Do or Table) to one of constructing the list of iteration values. This can be done in many ways, using Range, or Outer, or Array, or whatever is convenient for the particulars of your problem. Table uses exactly the same syntax but builds the output as a vector directly:

iters = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
Table[Total[i], {i, iters}]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.