11
$\begingroup$

There are some other questions on this topic but I could not get an answer from reading them. What I want to do is use Apply on some of the arguments of a function, h, and then Map on another argument. Here is what I attempted:

Map[Apply[{h[#, ##]} &, {a, b}] &, {1, 2}]
(* ===>{{h[a, a, b]}, {h[a, a, b]}} *)

The elements I want to Map over never get used. But this is not what I want. I want just

{h[1,a,b],h[2,a,b]}

I could use Table instead of Map but it's slow (slower than just using Apply twice) and I was hoping Map would be faster.

I understand that Apply is using both # and ## but I'm not sure what syntax is correct to force the first Slot to be used by Map instead of Apply.

EDIT: This is more like what I actually want to do:

Map[Apply[{h1[#, ##],h2[#, ##]} &, {RandomReal[], RandomReal[]}] &, {1, 2}]

So I want output as

{{h1[1, a1,b1], h2[1, a1,b1]},{h1[2, a2,b2], h2[2, a2,b2]}}

where I a's and b's are the random numbers. So to get this, I think the order of Apply and Map is important.

$\endgroup$
8
$\begingroup$

One option is to separate the slots by using an explicit Function for the second argument

Map[Function[arg, Apply[{h[arg, ##]} &, {a, b}]], {1, 2}]

Regarding your updated question. The approach is the same

Map[Function[arg, Apply[{h1[arg, ##], h2[arg, ##]} &, 
  {RandomReal[], RandomReal[]}]], {1, 2}]
$\endgroup$
6
$\begingroup$

Simply you could use:

Thread @ h[{1, 2}, a, b]
{h[1, a, b], h[2, a, b]}

If you can demonstrate how that fails in your application I will give other methods.


It was suggested that I use Sequence @@ {a, b} so as to keep {a, b} in the given form. I did not, because I was not clear as to the expected input format and because I felt that it would obscure the syntax.

Taking a guess as to your desired syntax, you might use:

f[head_][{q__}, {r__}] := Thread @ Unevaluated @ head[{q}, r]

f[h][{1, 2}, {a, b}]
{h[1, a, b], h[2, a, b]}

Unevaluated is needed for cases such as:

f[Print][{1, 2}, {a, b}];

1ab

2ab


Based on your updated question perhaps you want:

Through[{h1, h2} @@ RandomReal[1, 2] ~Prepend~ #] & /@ {1, 2}

Or

Through[{h1, h2}[#, Sequence @@ RandomReal[1, 2]]] & /@ {1, 2}

But if this is really representative of your usage there is probably a faster way.

$\endgroup$
  • 1
    $\begingroup$ Maybe use Sequence @@ {a, b} to preserve the input in the given form ? $\endgroup$ – b.gates.you.know.what Dec 12 '12 at 16:56
  • $\begingroup$ @b.gatessucks I'm still not sure what is the input. Is it supposed to be the two expression {1, 2} and {a, b}? $\endgroup$ – Mr.Wizard Dec 12 '12 at 17:00
4
$\begingroup$

Version 11.3 introduced Curry which can be used to good effect here:

Map[Apply[Curry[{h[##]} &, {3, 1, 2}], {a, b}][#] &, {1, 2}]

(* {{h[1, a, b]}, {h[2, a, b]}} *)

Map[Apply[Curry[{h1[##], h2[##]} &, 3][#], {RandomReal[], RandomReal[]}] &, {1, 2}]

(* {{h1[1, 0.373787, 0.928873], h2[1, 0.373787, 0.928873]},
    {h1[2, 0.271899, 0.0866199], h2[2, 0.271899, 0.0866199]}} *)
$\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.