# Reproducing nested loops using Map?

I keep producing bits of code like the following:

stuff = Module[
{curTarget = #},
getRowsForUserAndTarget[u, #, curTarget] & /@ validUsers
] & /@ allTargets;


Basically, I'm iterating through all the targets and all the users. Using a For loop it would look something like this (in python):

res = []
for user in validUsers:
for curTarget in allTargets:
res.append(getRowsForUserAndTarget[u, user, curTarget])


It seems like I should be able to do this succinctly in map notation using something like:

getRowsForUserAndTarget[#userthing, #targetthing]& /@ validUsers /@ validTargets


but I don't know how to keep the mapped arguments from interfering with each other, or how to reference which one I mean; and I'm a little hazy about the order of iteration (validUsers would go first, then validTargets?)

Can someone set me straight? This would seem like a common pattern that I am abusing with my Module[] solution...

-
Plus you could use Function[{user, target}, getRowsForUserAndTarget[user, target]] if you want to give your arguments names instead of #. –  wxffles Apr 19 '12 at 20:30
Can I just say how happy I am with the Mathematica community? Such fast, friendly, thoughtful answers. Just the responses to this one question have taught me a great deal. –  shanusmagnus Apr 20 '12 at 4:42

Is this what you want?

l1 = {a, b, c};
l2 = {aa, bb, cc};
sth[#1, #2] & @@@ Tuples[{l1, l2}]

{sth[a, aa], sth[a, bb], sth[a, cc], sth[b, aa], sth[b, bb],
sth[b, cc], sth[c, aa], sth[c, bb], sth[c, cc]}

-
For this example, Tuples[sth[{a, b, c}, {aa, bb, cc}]] works as well. –  Guess who it is. Jul 6 '12 at 2:31

A couple of other options:

allTargets = {"a", "b", "c", "d"};
validUsers = {1, 2, 3};

Table[getRowsForUserAndTarget[u, j, i], {i, allTargets}, {j, validUsers}]

Outer[getRowsForUserAndTarget[u, #2, #] &, allTargets, validUsers, 1]


Both of these methods produce nested lists separating output elements for each validUsers element, whereas Tuples produces a flattened list. This can be either advantagous or problematic. You can flatten one level using Join @@ e.g. Join @@ Table

-
How badly does it hurt to type out getRowsForUserAndTarget... twice? ;) –  The Toad Apr 19 '12 at 22:30
@R.M in Firefox I can select and Ctrl-drag to copy text in the edit box. Manually typing {"a", "b", "c", "d"} took longer. –  Mr.Wizard Apr 19 '12 at 22:32
Table approach is very useful and makes very clear code. I use to recomend its usage too. The only detail to take into account is that sometimes you need to Flatten the output. –  FJRA Apr 20 '12 at 0:59
@FJRA if one wants the flat list produced by Tuples this is also an issue with Outer. I usually use Join @@ if as in this case there is a single level to flatten. –  Mr.Wizard Apr 20 '12 at 21:47