Given two lists $l_a = \{a_1, a_2, a_3\}$, $l_b = \{b_1, b_2, b_3, b_4\}$ and some function $f$ accepting two arguments, how can I produce a list of all values $f(a, b)$ for $a\in l_a$ and $b \in l_b$ using functional construction?
Asked
Active
Viewed 209 times
3 Answers
10
You could do Outer[f, la, lb] as already suggested. Alternatively you could do
Partition[Apply[f, Tuples[{la, lb}], {1}], Length[la]]
or
Table[f[ai,bi],{ai,la},{bi,lb}]
or
Array[f[la[[#1]], lb[[#2]]] &, {Length[la], Length[lb]}]
Sasha
- 7,373
- 36
- 47
-
1As for me the second option is great - I'm using list of matrices and I never thought about using them as iterators... – JaM Dec 21 '12 at 20:52
-
7
While Outer is the canonical function, in addition to the methods that Sasha shows you could use:
Distribute
lst1 = {1, 3, 5, 7};
lst2 = {2, 4, 6, 8};
Distribute[f[lst1, lst2], List]
{f[1, 2], f[1, 4], f[1, 6], f[1, 8], f[3, 2], f[3, 4], f[3, 6], f[3, 8], f[5, 2], f[5, 4], f[5, 6], f[5, 8], f[7, 2], f[7, 4], f[7, 6], f[7, 8]}
Through and Listable
SetAttributes[f, Listable]
f[a__][x_] := f[a, x]
f[lst1][lst2] // Through
Thread and Map
g[a__][x_List] := Thread @ g[a, #] & /@ x
g[lst1][lst2]
ReplaceList
In a comment Rojo suggested using ReplaceList which is quite elegant:
ReplaceList[{lst1, lst2}, {{___, a_, ___}, {___, b_, ___}} :> {a, b}]
Recursion
h[{a_, b__}, x___] := h[{b}, x] ~Prepend~ h[x, a]
h[{a_}, x___] := {h[x, a]}
h[lst1, lst2]
I rather like this last one. It works with multiple lists too:
h[{1, 2, 3}, {a, b}, {x, y}]
{{{h[1, a, x], h[1, a, y]}, {h[1, b, x], h[1, b, y]}}, {{h[2, a, x], h[2, a, y]}, {h[2, b, x], h[2, b, y]}}, {{h[3, a, x], h[3, a, y]}, {h[3, b, x], h[3, b, y]}}}
Formulated using linked lists for higher performance:
h[{a_, b__}, x___] := {h[x, a], h[{b}, x]}
h[{a_}, x___] := h[x, a]
h[{1, 2, 3}, {a, b}, {x, y}] // Flatten
{h[1, a, x], h[1, a, y], h[1, b, x], h[1, b, y], h[2, a, x], h[2, a, y], h[2, b, x], h[2, b, y], h[3, a, x], h[3, a, y], h[3, b, x], h[3, b, y]}
-
1If the intent doesn't imply nesting them, a nice one is also
ReplaceList[{{1, 2, 3}, {a, b}}, {{___, a_, ___}, {___, b_, ___}} :> {a, b}]– Rojo Dec 22 '12 at 15:40 -
@Rojo Similar to this answer which as you'll note I liked. May I include that in my answer? – Mr.Wizard Dec 23 '12 at 03:11
-
-
@Rojo for some reason I'm not getting
@notificationstoday. I looked at that answer briefly but I intended to return to it. In the context of a largerGridlayout I believe that different sections will not align. Sorry for not being responsive to your answer without prompting. – Mr.Wizard Dec 23 '12 at 11:25
2
ListConvolve
l1 = {a1, a2, a3}; l2 = {b1, b2, b3};
Union @@ ListConvolve[l1, l2, 1, l2, f, 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]} *)
Tuples - an alternative usage
Tuples[f[l1, l2]]
(* {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]} *)
To partition the flat lists above, use Partition or the new-in-Version-9 ArrayReshape:
ArrayReshape[%, {Length@l1, Length@l2}]
(* {{f[a1, b1], f[a1, b2], f[a1, b3]},
{f[a1, b4], f[a2, b1], f[a2, b2]},
{f[a2, b3], f[a2, b4], f[a3, b1]}}*)
kglr
- 394,356
- 18
- 477
- 896
Outer[f,la, lb]wherelaandlbare your lists – rm -rf Dec 21 '12 at 20:22Outerusing functional style? – JaM Dec 21 '12 at 20:32f[#, k] & /@ {x1,x2}/. k -> # & /@ {y1, y2, y3}? – Dr. belisarius Dec 21 '12 at 20:45/. k -> # &– JaM Dec 21 '12 at 21:07