1
$\begingroup$

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

$\endgroup$
8
  • 1
    $\begingroup$ 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. $\endgroup$ Sep 21, 2012 at 12:12
  • $\begingroup$ 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. $\endgroup$
    – Noon Silk
    Sep 21, 2012 at 12:20
  • 1
    $\begingroup$ I specifically discussed this issue here $\endgroup$ Sep 21, 2012 at 12:21
  • $\begingroup$ Could you maybe talk about your actual problem that is requiring you to do that sort of construction? $\endgroup$ Sep 21, 2012 at 12:21
  • 1
    $\begingroup$ I suppose something like Outer[SomeFunc[dim, g, #1, #2] &, opList, subList, 1], then? $\endgroup$ Sep 21, 2012 at 12:34

2 Answers 2

5
$\begingroup$

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.

$\endgroup$
1
  • $\begingroup$ 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. $\endgroup$
    – Noon Silk
    Sep 21, 2012 at 12:50
6
$\begingroup$

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

$\endgroup$
2
  • $\begingroup$ 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. $\endgroup$
    – Artes
    Sep 21, 2012 at 13:34
  • $\begingroup$ @Artes, thank you. $\endgroup$ Sep 22, 2012 at 11:25

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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