Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

I am looking for an elegant way to Map multiple functions over an array. My problem looks something like this:

Consider a list of functions:

f = {f1,f2,f3,f4} (* example, can be larger *)

And an array:

A = {{a1, b1, c1, d1, e1}, {a2, b2, c2, d2, e2}, {a3, b3, c3, d3, e3}}; (*example, can be larger*)

Q1: I’d like to map the functions in f over the array A so that the final result looks like:

B= {{1 - a1, f1[a1]*b1, f2[a1]*c1, f3[a1]*d1, f4[a1]*e1}, {1 - a2, 
f1[a2] b2, f2[a2] c2, f3[a2] d2, f4[a2] e2}, {1 - a3, f1[a3] b3, 
f2[a3] c3, f3[a3] d3, f4[a3] e3}}

Sample input/output

Q2: How do I map the functions a little differently so that the output looks like:

c= {{a1, f1[a1] b1, f2[b1] c1, f3[c1] d1, f4[d1] e1}, {a2, f1[a2] b2, 
f2[b2] c2, f3[c2] d2, f4[d2] e2}, {a3, f1[a3] b3, f2[b3] c3, 
f3[c3] d3, f4[d3] e3}} // tf

Alternate mapping

share|improve this question
    
Just writing it out func[{a_, b_, c_, d_}] := {1 - a, b f1[a], c f2[a], d f3[a], e f4[a]} and then func/@A is pretty elegant, I think. –  Pickett Mar 21 at 1:41
    
The issue is that the array sizes and functions I show are examples and in reality the arrays/functions are quite large so writing it out gets pretty tedious… –  Pam Mar 21 at 1:45

2 Answers 2

up vote 5 down vote accepted

Here's a way to write out the map concisely:

Q1:

{1 - #, ##2} Through[Join[{1 &}, f]@#] & @@@ A
(* {{1 - a1, b1 f1[a1], c1 f2[a1], d1 f3[a1], e1 f4[a1]}, 
    {1 - a2, b2 f1[a2], c2 f2[a2], d2 f3[a2], e2 f4[a2]}, 
    {1 - a3, b3 f1[a3], c3 f2[a3], d3 f3[a3], e3 f4[a3]}} *)

Q2:

Join[{1 - #[[1]]}, MapThread[#3 #@#2 &, {f, Most@#, Rest@#}]] & /@ A
(* {{1 - a1, b1 f1[a1], c1 f2[b1], d1 f3[c1], e1 f4[d1]}, 
    {1 - a2, b2 f1[a2], c2 f2[b2], d2 f3[c2], e2 f4[d2]}, 
    {1 - a3, b3 f1[a3], c3 f2[b3], d3 f3[c3], e3 f4[d3]}} *)
share|improve this answer
    
Holy crap… never knew there was a function called Through… this is brilliant! –  Pam Mar 21 at 1:57
    
Any take on Q2 above? –  Pam Mar 21 at 1:57
    
BTW, brilliant @rm-rf. –  kale Mar 21 at 2:03
    
@Pam See edit... there probably are other ways, but this does the job. –  rm -rf Mar 21 at 2:06

I was thinking about a more readable way because your question under rm's answer

Any take on Q2 above?

slightly indicates that you couldn't take it further although the idea to solve Q2 was similar. I guess my solution is in no way as easy as I had hoped it to be, but I give it anyway.

What it does is that it separates the tasks a bit. The distributor takes your list of functions and exactly one sublist like e.g. {a1, b1, c1, d1, e1} and builds up the result. For your Q1 this is just calculating 1-a1 and creating all the x1*fn[a1].

distributor[funcs_][vec_] :=
 Join[{1 - First[vec]}, #2*#1[First[vec]] & @@@ Transpose[{funcs, Rest[vec]}]
  ]

And now you can map the distributor over your A

distributor[f] /@ A

Mathematica graphics

To solve your second problem Q2 you only need to adjust the distributor which now includes a call to Partition to create sequence {{a1, b1}, {b1, c1}, {c1, d1}, {d1, e1}} we need:

distributor2[funcs_][vec_] :=
 Join[{1 - First[vec]}, #2[[2]]*#1[#2[[1]]] & @@@ Transpose[{funcs, Partition[vec, 2, 1]}]
  ]

distributor2[f] /@ A

Mathematica graphics

share|improve this answer
    
This is a very nice answer as well. –  Pam Mar 21 at 2:47

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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