2
$\begingroup$

I'm trying to learn the functional style which seems to prevail in Mathematica. I'm having trouble accomplishing the following:

Let's say I have multiple lists of arbitrary data (using two lists here to keep it simple):

a = {1,2,3,4,5,6}
b = {1,1,2,2,3,3}

I also have multiple arbitrary functions (again using two to keep it simple) which all take the same inputs in the same order, but use them to generate different outputs:

f = Function[{u,v},{{u^2,u*v},{-u*v,v^2}}]
g = Function[{u,v},{{u^2,1},{-1,v^2}}]

I understand how to build lists of results, threading over lists a,b, with MapThread:

fOut = MapThread[f,{a,b}]
gOut = MapThread[g,{a,b}]

However, because in reality there are dozens of functions (f,g,etc.) and dozens of lists of data (a,b,etc.), I end up with dozens of MapThread commands, each with the same long list of arguments, creating a wall of text that is far from elegant-looking. So I tried to merge it into a single MapThread command, which didn't work:

{fOut,gOut} = MapThread[{f,g},{a,b}]

Is there a way to MapThread many functions onto many lists of data (assuming each function expects the data in the same order)? If possible, I would like to avoid creating new variables because the functions are intended to be compiled, and I think it would create redundant data.

$\endgroup$
3
  • 1
    $\begingroup$ Does this generate the result you expect: (# @@@ Transpose@{a, b}) & /@ {f, g}? Or even: SetAttributes[{f, g}, Listable]; (# @@ {a, b}) & /@ {f, g}. $\endgroup$ Jan 11, 2014 at 17:28
  • $\begingroup$ That first one does exactly what I want. Thanks! Now I just need to understand what the hell it's doing. $\endgroup$
    – phosgene
    Jan 11, 2014 at 17:35
  • 1
    $\begingroup$ You can do : Outer[#1 @@ #2 &, {f, g}, Transpose[{a, b}], 1] $\endgroup$
    – andre314
    Jan 11, 2014 at 18:02

1 Answer 1

3
$\begingroup$

It is not entirely clear to me what your larger problem looks like. If you have the same set of lists each time and merely want to MapThread a series of functions across them you can use a simple construct such as:

a = {1, 2, 3, 4, 5, 6};
b = {1, 1, 2, 2, 3, 3};

MapThread[#, {a, b}] & /@ {f, g}
{{f[1, 1], f[2, 1], f[3, 2], f[4, 2], f[5, 3], f[6, 3]},
 {g[1, 1], g[2, 1], g[3, 2], g[4, 2], g[5, 3], g[6, 3]}}

If you have a more involved operation in mind please describe it in greater detail.

$\endgroup$
6
  • $\begingroup$ That was exactly what I needed. Of the three suggestions I've seen so far (all of which work), this one has the most concise and easy-to-read syntax, and also the highest (uncompiled) performance by a small margin. $\endgroup$
    – phosgene
    Jan 11, 2014 at 18:23
  • $\begingroup$ @user2790167 If you give a more representative example of your actual operation we may be able to recommend a better approach. For example, MapThread will unpack packed arrays, and can therefore significantly limit performance in some cases. $\endgroup$
    – Mr.Wizard
    Jan 11, 2014 at 18:38
  • $\begingroup$ I'm not using any packed arrays (to my knowledge). I'm actually writing code inside a Compile command. The fundamental operations are floating-point linear algebra. $\endgroup$
    – phosgene
    Jan 11, 2014 at 18:59
  • $\begingroup$ ...including construction of matrices from data (similar to functions f,g in my example). I've already written the whole thing in the procedural style (a wall of text to be sure), and I wanted to make the code shorter and easier to read. $\endgroup$
    – phosgene
    Jan 11, 2014 at 19:08
  • $\begingroup$ Map[MapThread[#,{a,b}]&,{f,g}] compiles seemingly without error. However, when it's called, it fails with this error: "Compiled expression Function[{u,v},{{u^2,u v},{-u v,v^2}}] should be a machine-size real number. >>", then executes the uncompiled version instead, which is an order of magnitude slower. A plain MapThread command makes a good compiled function, but it seems not to like nested Map[MapThread] commands for some reason. $\endgroup$
    – phosgene
    Jan 11, 2014 at 21:58

Your Answer

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

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