# Table with multiple iterators running parallel

I want to use Table to generate a list, but it only allows one iterator to increment at a time. So in

Table[i*r, {i, 0, 5}, {r, 0, 5}]


r will run 0 through 5 for i = 0, then change i and run through r again etc., giving 36 elements in a 6 x 6 array. But I want a list of only 6 elements, so that i and r are changed at the same time, in parallel. So it would give 0*0, then 1*1, 2*2 etc. Giving the output of:

{0, 1, 4, 9, 16, 25}  (* <-This is what I want. *)


Is this possible with Table or anything else?

Also I know I could do:

Table[i*i, {i,0,5}]


But this is just an example, and in my project this way won't work. Also if at all possible I would like to use a list for one iterator's values, but this isn't so important.

-
Let's assume we had this Table which increments both i and r at the same time, so i and r are always equal. Can you tell me only one example where you can create a list with those two iterators which you cannot create with a single iterator? Otherwise, I won't understand what you try to do. –  halirutan Jul 23 '14 at 10:36
Range[0, 5]^2 –  eldo Jul 23 '14 at 10:38
@halirutan My project is an engine, and the cylinders are in Table so to have many, Table increases the x already. But also I need to have an iterator to add a few degrees to have firing order, which will follow a few number such as 1,3,4,2. So the iterators must follow 0->2 Pi, and 1,3,4,2 –  ptolemy0 Jul 23 '14 at 10:45
So lets say you want a list which includes the cylinder number and the angle-shift for each cylinder of your engine, how about: cyl=8;Table[{i,(i-1)*2Pi/(cyl)},{i,cyl}]? –  halirutan Jul 23 '14 at 11:15
@ptolemy0 Thanks for the Accept. Since that is apparently what you wanted I will see if I can make those functions perform better, if I have time. –  Mr.Wizard Jul 23 '14 at 13:51

There are two easy approaches that come to mind. The first is to simply use MapThread.

MapThread[foo, {Range[0, 4], Range[24, 32, 2]}]

{foo[0, 24], foo[1, 26], foo[2, 28], foo[3, 30], foo[4, 32]}


If you are collecting all results this is probably a perfectly good approach as memory is unlikely to be a problem.

The second is to define the relationship between the two iterators and then use only one. For the example above the second iterator can be generated from the first with the formula 2 (# + 12). We could then write:

Table[foo[i, 2 (i + 12)], {i, 0, 4}]

{foo[0, 24], foo[1, 26], foo[2, 28], foo[3, 30], foo[4, 32]}


I suppose you would like a syntax more like Table. The question is then how to automate this.

For MapThread I propose:

SetAttributes[pTable1, HoldAll]

pTable1[expr_, iter : {_Symbol, __} ..] :=
MapIndexed[Set, Hold[iter][[All, 1]]] /. List -> Slot /. _[x__] :>
Block[{x}, expr] &,
Range @@@ Rest /@ {iter}
]


Now:

pTable1[foo[x, y], {x, 0, 4}, {y, 24, 32, 2}]

{foo[0, 24], foo[1, 26], foo[2, 28], foo[3, 30], foo[4, 32]}


While working on the second method it occurred to me that a different syntax is superior. Ranges should instead be given as a starting value and a step size rather than start,end,step, then a single repetition value for all iterators should be given. This both shortens syntax and assures agreement of length.

SetAttributes[pTable2, HoldAll]

pTable2[expr_, iter : {_Symbol, __} .., n_Integer] :=
Module[{Z},
Hold[iter] /. {i_, a_, s_: 1} :> (i = a - s + s Z) /. _[x__] :>
Block[{x}, Table[expr, {Z, n}]]
]


Example use:

pTable2[foo[x, y], {x, 0}, {y, 24, 2}, 5]

{foo[0, 24], foo[1, 26], foo[2, 28], foo[3, 30], foo[4, 32]}


We can prettify either function by adding syntax highlighting similar to Table, indicating the scoped Symbols in the iterators:

SyntaxInformation[pTable2] = SyntaxInformation[Table];


Now input appears as:

As indicated x and y are correctly scoped, and evaluation is as in Table:

x = y = "Fail!";
bar := foo[x, y];
pTable2[bar, {x, 0}, {y, 24, 2}, 5]

{foo[0, 24], foo[1, 26], foo[2, 28], foo[3, 30], foo[4, 32]}

-

You can use a Table with variable iterator limit. e.g.

Table[f[i, r], {i, 0, 5}, {r, {i}}]

{{f[0, 0]}, {f[1, 1]}, {f[2, 2]}, {f[3, 3]}, {f[4, 4]}, {f[5, 5]}}


Or

Table[f[i, r], {i, 0, 5}, {r, 0, i, 2}] // TableForm

f[0,0]
f[1,0]
f[2,0]  f[2,2]
f[3,0]  f[3,2]
f[4,0]  f[4,2]  f[4,4]
f[5,0]  f[5,2]  f[5,4]

-