4
$\begingroup$

Consider a function f and a list p={a,b,c}. I want to get a list of

f[a,a]
f[a,b]
f[a,c]
f[b,a]
f[b,b]
f[b,c]
f[c,a]
f[c,b]
f[c,c]

In real use, p can have higher dimensions, and f may take more arguments, e.g. I may need to generate a list of f[a,a,a,a] through f[z,z,z,z]. Is there a cleaner way to do this other than making lists that approximately repeat the elements of p then use MapThread? e.g.

p={a,b}
p1 = {a, a, b, b}
p2 = {a, b, a, b}
MapThread[f, {p1, p2}]

Here, a, b can be matrices

$\endgroup$
3
  • $\begingroup$ What about Outer? $\endgroup$
    – chuy
    Commented Jun 20, 2019 at 19:31
  • $\begingroup$ @chuy Thanks! but Outer may not be a good fit when a,b ... are matrices. $\endgroup$ Commented Jun 20, 2019 at 19:35
  • $\begingroup$ Just realized that p = {a, b, c}; Distribute[f[p, p], List] works $\endgroup$ Commented Jun 20, 2019 at 19:44

2 Answers 2

10
$\begingroup$

You can use Tuples:

Tuples[f[{a, b, c}, {a, b, c}]]

{f[a, a], f[a, b], f[a, c], f[b, a], f[b, b], f[b, c], f[c, a], f[c, b], f[c, c]}

f @@@ Tuples[{a, b, c}, 2]

same result

Tuples[f[{a, b}, {r, s, t}, {x, y}]]

{f[a, r, x], f[a, r, y], f[a, s, x], f[a, s, y], f[a, t, x], f[a, t, y], f[b, r, x], f[b, r, y], f[b, s, x], f[b, s, y], f[b, t, x], f[b, t, y]}

f @@@ Tuples[{{a, b}, {r, s, t}, {x, y}}]

same result

p = {a, b};
p1 = {a, a, b, b};
Tuples[f[p, p1]]

{f[a, a], f[a, a], f[a, b], f[a, b], f[b, a], f[b, a], f[b, b], f[b, b]}

$\endgroup$
5
  • $\begingroup$ Oops, might need to be changed when a,b,c are matrices? $\endgroup$ Commented Jun 20, 2019 at 19:16
  • $\begingroup$ Thanks! But when I use e.g. 2x2 matrices for a, b, c, p={a,b,c}, then Tuples[KroneckerProduct[p, p]] // Dimensions is {262144, 9, 4}, and does not give 9 4-by-4 matrices... $\endgroup$ Commented Jun 20, 2019 at 19:26
  • 2
    $\begingroup$ @egwenesedai, does KroneckerProduct@@@Tuples[p, 2] work? $\endgroup$
    – kglr
    Commented Jun 20, 2019 at 19:28
  • $\begingroup$ Works, thanks a lot! $\endgroup$ Commented Jun 20, 2019 at 19:29
  • 2
    $\begingroup$ you can also use Tuples[kp[p, p]] /. kp -> KroneckerProduct (to prevent KroneckerProduct evaluating before Tuples does its job) $\endgroup$
    – kglr
    Commented Jun 20, 2019 at 19:31
7
$\begingroup$

You could also use Tuples as follows:

Tuples[f[a,b,c], 2]

{f[a, a], f[a, b], f[a, c], f[b, a], f[b, b], f[b, c], f[c, a], f[c, b], f[c, c]}

If f evaluates, and you want to do this for matrices, you could do:

p = RandomInteger[1, {3, 2, 2}];
Block[{KroneckerProduct}, Tuples[KroneckerProduct @@ p, 2]] //Dimensions

{9, 4, 4}

$\endgroup$
1
  • $\begingroup$ Thanks! That's one clever use for Block $\endgroup$ Commented Jun 21, 2019 at 21:33

Your Answer

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

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