8
$\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$
8
  • 3
    $\begingroup$ Outer $\endgroup$
    – Sektor
    Jun 4, 2015 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, 2015 at 17:46
  • 5
    $\begingroup$ g[x, ##] & @@@ Tuples[{X, Y}] $\endgroup$ Jun 4, 2015 at 18:10
  • 1
    $\begingroup$ Actually, @march's use of Outer[] can be simplified: Outer[g[x, ##] &, X, Y] // Flatten. $\endgroup$ Jun 5, 2015 at 3:41
  • 1
    $\begingroup$ @J. M. SlotSequence. One of many things that could revolutionize my life. $\endgroup$
    – march
    Jun 5, 2015 at 3:55

2 Answers 2

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$
1
  • $\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$ Feb 8, 2018 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.