Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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.)

share|improve this question
1  
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. –  J. M. 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
1  
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? –  J. M. Sep 21 '12 at 12:21
1  
I suppose something like Outer[SomeFunc[dim, g, #1, #2] &, opList, subList, 1], then? –  J. M. Sep 21 '12 at 12:34
show 3 more comments

2 Answers 2

up vote 3 down vote accepted

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.

share|improve this answer
    
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
add comment

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

share|improve this answer
    
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
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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