# Proper way to deal with lists and map

So, I wanted to do something that I assumed would be really simple. Given two lists, $A = \{a_1, a_2, ...\}, B = \{ ... \}$, I wanted to take a function $f(a, b)$ and generate a list with $\{ f(a_1, b_1), f(a_1, b_2), ... \}$, i.e. just the cartesian product.

Of course, it's really easy, in principal, to do this:

f[#1, #2] & @@@ Outer[List, {a1, a2, a3}, {b1, b2}]


The annoyance comes in when the elements are themselves lists. In this case, everything breaks. Ridiculous things start happening.

There is a "trivial" solution; just use dummy variables in the above statement, and replace it in with what I want later. But to me this seems fundamentally wrong somehow. Surely it should be possible to work with lists of arbitrary type; and not have to "protect" your mapping functions from lists of lists.

Any thoughts? Am I missing some fundamental strategy here?

-- Edit:

To elaborate more, I'm actually trying to make the following work:

dim = 2; (* Say *)
Table[
SomeFunc[dim, g, op, #] & /@
Subsets[Range[dim], {i}], {i, 1, dim}
]


op previously was a single matrix; but now I need it to be a list of matricies. That is so say, I want to run "SomeFunc" for each matrix in that list, and also each of the results that come from the Subset function (note, of course, that Subsets returns lists.)

-
You should be doing something like Outer[f, {a1, a2, a3}, {b1, b2}]. You will also want to look into the documentation for Outer[]; in particular, its support of level arguments. –  Ｊ. Ｍ. Sep 21 '12 at 12:12
Okay, so I actually need to evaluate f(x, y, a, b). So I don't think Outer will work in that case. Well, maybe I could make it work ... but I think this question still is relevant. –  Noon Silk Sep 21 '12 at 12:20
I specifically discussed this issue here –  Leonid Shifrin Sep 21 '12 at 12:21
Could you maybe talk about your actual problem that is requiring you to do that sort of construction? –  Ｊ. Ｍ. Sep 21 '12 at 12:21
I suppose something like Outer[SomeFunc[dim, g, #1, #2] &, opList, subList, 1], then? –  Ｊ. Ｍ. Sep 21 '12 at 12:34

To resolve this question:

This construction would do what you want, it seems:

opList = Array[C, {3, 2, 2}]; (* list of matrices *)
sList = Array[K, {3, 4}]; (* list of vectors *)

Outer[f, opList, sList, 1]
{{f[{{C[1, 1, 1], C[1, 1, 2]}, {C[1, 2, 1], C[1, 2, 2]}},
{K[1, 1], K[1, 2], K[1, 3], K[1, 4]}],
f[{{C[1, 1, 1], C[1, 1, 2]}, {C[1, 2, 1], C[1, 2, 2]}},
{K[2, 1], K[2, 2], K[2, 3], K[2, 4]}],
f[{{C[1, 1, 1], C[1, 1, 2]}, {C[1, 2, 1], C[1, 2, 2]}},
{K[3, 1], K[3, 2], K[3, 3], K[3, 4]}]},
{f[{{C[2, 1, 1], C[2, 1, 2]}, {C[2, 2, 1], C[2, 2, 2]}},
{K[1, 1], K[1, 2], K[1, 3], K[1, 4]}],
f[{{C[2, 1, 1], C[2, 1, 2]}, {C[2, 2, 1], C[2, 2, 2]}},
{K[2, 1], K[2, 2], K[2, 3], K[2, 4]}],
f[{{C[2, 1, 1], C[2, 1, 2]}, {C[2, 2, 1], C[2, 2, 2]}},
{K[3, 1], K[3, 2], K[3, 3], K[3, 4]}]},
{f[{{C[3, 1, 1], C[3, 1, 2]}, {C[3, 2, 1], C[3, 2, 2]}},
{K[1, 1], K[1, 2], K[1, 3], K[1, 4]}],
f[{{C[3, 1, 1], C[3, 1, 2]}, {C[3, 2, 1], C[3, 2, 2]}},
{K[2, 1], K[2, 2], K[2, 3], K[2, 4]}],
f[{{C[3, 1, 1], C[3, 1, 2]}, {C[3, 2, 1], C[3, 2, 2]}},
{K[3, 1], K[3, 2], K[3, 3], K[3, 4]}]}}


The level argument 1 in Outer[] essentially tells Outer[] to treat everything in level 1 (that is, the elements of the input lists) as atomic, instead of having Outer[] treat the first list as a rank-3 tensor and the second list as a matrix.

-
Almost; I had to add an extra Flatten in front of the Outer; but this definitely was the right idea - I didn't know about using pure functions in like this. Thanks for your help. –  Noon Silk Sep 21 '12 at 12:50

Is this what you are after ?

a = {a1, a2, a3}
b = {b1, b2, b3}

Distribute[f[a, b], List]


{f[a1, b1], f[a1, b2], f[a1, b3], f[a2, b1], f[a2, b2], f[a2, b3], f[a3, b1], f[a3, b2], f[a3, b3]}

And as suggested by Artes the equivalence of solutions can be shown by:

a = Array[c, {3, 2, 2}]; b = Array[k, {3, 4}];
Distribute[f[a, b], List] === Flatten[Outer[f, a, b, 1], 1]


True

-
Nice solution +1, one can add e.g. for a = Array[c, {3, 2, 2}]; b = Array[k, {3, 4}]; then Distribute[f[a, b], List] === Flatten[Outer[f, a, b, 1], 1] yields True. –  Artes Sep 21 '12 at 13:34
@Artes, thank you. –  image_doctor Sep 22 '12 at 11:25