7
$\begingroup$

I have two lists

X = {1, 2, 3};
Y = {5, 6, 7, 8};

I want to apply function g[x,y_,z_] to all pairs from X*Y, so I need to get a list {g[x,1,5],g[x,1,6]…,g[x,3,8]}

I came up with this syntax

g[x, ##] &@(Sequence @@ #) & /@ Tuples[{X, Y}]

and it gives what I want.

Is there more elegant way to do it?

Update: The most elegant way is proposed by belisarius:

f[1, ##] & @@@ Tuples[{x, y}]

I compared performance of three methods

f[x_, y_, z_] := x + y + z;
bel[x_, y_] := f[1, ##] & @@@ Tuples[{x, y}];
mar[x_, y_] := Flatten[Outer[f[1, ##] &, x, y]];
bkow[x_, y_] := f[1, ##] &@(Sequence @@ #) & /@ Tuples[{x, y}];

benchmark[f_, n_] := 
  Module[{l = Range[1, n]}, 
   Mean@Table[First@AbsoluteTiming[f[l, l]], {20}]];

TableForm[
   Table[benchmark[fun, n]/n/n, {fun, {bel, mar, bkow}}, {n, #}], 
   TableHeadings -> {{"bel", "mar", "bkow"}, #}] &@{10, 30, 100, 300, 
  1000}

and it looks like Outer is a bit faster, but the f[1, ##] & @@@ Tuples[{x, y}] definitely looks cleaner. Results are normalized over n^2

enter image description here

$\endgroup$
  • 3
    $\begingroup$ Outer $\endgroup$ – Sektor Jun 4 '15 at 17:30
  • 3
    $\begingroup$ Or Flatten[Outer[g[x, #1, #2] &, X, Y]]. @bills I think it needs Sequence@# in your expression? $\endgroup$ – march Jun 4 '15 at 17:46
  • 5
    $\begingroup$ g[x, ##] & @@@ Tuples[{X, Y}] $\endgroup$ – Dr. belisarius Jun 4 '15 at 18:10
  • 1
    $\begingroup$ Actually, @march's use of Outer[] can be simplified: Outer[g[x, ##] &, X, Y] // Flatten. $\endgroup$ – J. M. is away Jun 5 '15 at 3:41
  • 1
    $\begingroup$ @J. M. SlotSequence. One of many things that could revolutionize my life. $\endgroup$ – march Jun 5 '15 at 3:55
6
$\begingroup$

As requested, I'm copying the above comment as an answer:

g[x, ##] & @@@ Tuples[{X, Y}]

seems an elegant way to me

$\endgroup$
  • $\begingroup$ I'd like to add to this answer that Outer has the advantage over g[x, ##] & @@@ Tuples[{X, Y}] when it comes to packed arrays, since Outer doesn't unpack while @@@ does. $\endgroup$ – Sjoerd Smit Feb 8 '18 at 10:45
1
$\begingroup$
Distribute[g[x, X, Y], List] 

{g[x, 1, 5], g[x, 1, 6], g[x, 1, 7], g[x, 1, 8],
g[x, 2, 5], g[x, 2, 6], g[x, 2, 7], g[x, 2, 8],
g[x, 3, 5], g[x, 3, 6], g[x, 3, 7], g[x, 3, 8]}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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