Mapping multiple functions over an array

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}}

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

• 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. Commented Mar 21, 2014 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
Commented Mar 21, 2014 at 1:45

2 Answers

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]}} *)
• Holy crap… never knew there was a function called Through… this is brilliant!
– Pam
Commented Mar 21, 2014 at 1:57
• Any take on Q2 above?
– Pam
Commented Mar 21, 2014 at 1:57
• BTW, brilliant @rm-rf.
– kale
Commented Mar 21, 2014 at 2:03
• @Pam See edit... there probably are other ways, but this does the job.
– rm -rf
Commented Mar 21, 2014 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

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

• This is a very nice answer as well.
– Pam
Commented Mar 21, 2014 at 2:47