I'm attempting to MapThread a function of two lists that requires the index of the list values. For example,

MapThread[#1*i+#2*j&,{{a,b,c},{e,f,g}}]


Where #1 represents the value from list 1, #2 the value from list 2, i the index of list 1, and j the index of list 2. The expected output is

{a+e,2b+2f,3c+3g}


This would presumably be accomplished by an "IndexedMapThread" function, but I'm not sure something like that exists in Mathematica currently.

Any suggestions on how to do this simply?

Update:

ClearAll[imtF]
imtF[foo_] := Module[{i = 1}, foo[#, i++] & /@ Transpose@#] &


Examples:

imtF[#2 (Plus @@ #) &][{{a, b, c}, {e, f, g}}]
(* {a + e, 2 (b + f), 3 (c + g)} *)

xx = {{a, b, c}, {e, f, g}, {x, y, z}};
imtF[#2 (Plus @@ #) &][xx]
(* {a + e + x, 2 (b + f + y), 3 (c + g + z)} *)

imtF[Plus @@ Times@## &][xx]
(* {a + e + x, 2 b + 2 f + 2 y, 3 c + 3 g + 3 z} *)

fn[x_, i_] := #*i + #2*i + #3^i & @@ x (*Mr.W's example modified *)
imtF[fn][xx]
(* {a + e + x, 2 b + 2 f + y^2, 3 c + 3 g + z^3} *)


Range[Length@#] Thread@+## &[{a, b, c}, {e, f, g}]
MapIndexed[# #2[] &, Thread[Plus[##]]] &[{a, b, c}, {e, f, g}]
MapIndexed[# #2[] &, +## & @@@ ({##}\[Transpose])] &[{a, b, c}, {e, f, g}]
MapIndexed[+(## & @@ # ) #2[] &, #\[Transpose]] &@{{a, b, c}, {e, f, g}}


all give

(* {a + e, 2 (b + f), 3 (c + g)} *)

• aaahh, penguins working on the same q/a as you again, tell me which is neater ? – penguin77 Apr 15 '15 at 18:50
• It seems to me than none of this is general. By my reading the OP is not asking merely for a particular mathematical operation but rather a general method of application. – Mr.Wizard Apr 15 '15 at 19:23
• @penguin77 it is a small world :) – kglr Apr 15 '15 at 19:24
• @Mr.Wizard, good point, thank you. Updated with something that works with general two-arg functions. – kglr Apr 15 '15 at 19:57
• Now you get my vote. :-) – Mr.Wizard Apr 15 '15 at 20:09

You may consider this

MapIndexed[Times, #] & /@ {{a, b, c}, {e, f, g}}  // Plus @@ # &

(* {{a + e}, {2 b + 2 f}, {3 c + 3 g}} *)


MapIndexed applies a function (in your example Times to all elements of the list giving part specification (in your example i respectively j) as the second argument. The two resulting lists are then added in the postfix expression.

You may flatten to get

 % //Flatten
(* {a + e, 2 b + 2 f, 3 c + 3 g} *)


Update for fun. I know it's not part of q/a. However the numerous different answers are well suited for gaining insight on performance. Here the results with a data set {Range @ 10^6, Range @ 10^6}. (kguler's examples correspond to the non updated version posted). kguler's Range[Length@#] Thread@+## &[*dataset*] is about 45 times faster than the slowest solution proposed. This is simply amazing and gives ground for analyzing what makes one approach faster than another. PS: Interested in ColorFunction -> AntarcticColor ? Here the "receipt": AntarcticColor[ z_ ] := RGBColor[z/2, 1 - z, 1];

PS,PS: hmmm, Wizards waddling behind penguins ?!

• ++1 for AntarcticColor:) – kglr Apr 15 '15 at 21:50

Since it would seem that your index values i and j will always be the same you need only to Transpose your input and use MapIndexed:

MapIndexed[
#[]*#2[] + #[]*#2[] &,
{{a, b, c}, {e, f, g}}\[Transpose]
]

{a + e, 2 b + 2 f, 3 c + 3 g}


Here #[] is the first element, #[] is the second element, and #2[] is the (universal) index.

To make this easier to use consider rewriting your function as follows:

fn[x_, {i_}] := #*i + #2*i + #3^i & @@ x

MapIndexed[fn, {{a, b, c}, {e, f, g}, {x, y, z}}\[Transpose]]

{a + e + x, 2 b + 2 f + y^2, 3 c + 3 g + z^3}


A third parameter is included for illustration. i represents the universal index.

At face value there is this solution:

IndexedMapThread[list1_,list2_] :=

IndexedMapThread[{a, b, c}, {d, e, f}]
(* {a + d, 2 b + 2 e, 3 c + 3 f} *)

• This is throwing an error at me "MapThread called with 5 arguments – penguin77 Apr 15 '15 at 19:38
• Crap, sorry, I forgot to wrap the lists and ranges into curly braces. Fixed. And it still got upvoted :D, I guess everybody just looked at the code, thought "seems legit" and didn't test it :-) – LLlAMnYP Apr 15 '15 at 19:40
• Incidentally one could assume that the lists are the same length and use: MapThread[(#1*#3+#2*#4 &),{list1,list2, #, #}] & @ Range @ Length @ list1 or the equivalent With. – Mr.Wizard Apr 15 '15 at 19:43
• I'm a bit concerned about possible conflicts of #1 and # in this code snippet (what if it substitutes the range into the first argument of MapThread? I don't have Mathematica handy right now to check), but following the gist of your comment I'd prefer then MapThread[(#3(#1+#2)&),{list1,list2,#}] & @ Range @ Length @ list1. No need to assume anything, as MapThread will throw an error if the lists are not of the same length anyway. – LLlAMnYP Apr 15 '15 at 19:47
• @LLlAMnYP, it also already happened to me. HINT: Always copy immediately the posted code back into Notebook and evaluate, for cross-checking. Making it a good habit. – penguin77 Apr 15 '15 at 19:49

Here is definition for indexedMapThread that works for any number of lists so long as they are all equal in length.

indexedMapThread[args : {_List ..}] :=
Module[{sizes = Length /@ args, scalars},
If[Not[Equal @@ sizes], Return[\$Failed]];
scalars = Range@sizes[];
Expand @ Flatten @ Thread[{#1 Plus[##2]}&[scalars, Sequence @@ args]]]


{a, 2 b, 3 c}

indexedMapThread @ {{a, b, c}, {e, f, g}}

{a + e, 2 b + 2 f, 3 c + 3 g}

indexedMapThread @ {{a, b, c}, {e, f, g}, {h, i, j}}

{a + e + h, 2 b + 2 f + 2 i, 3 c + 3 g + 3 j}


Not sure why you'd need differing variable names, since the index would always be same, but, that aside:

imt[f_, l_, v_] := Module[Evaluate@v, MapThread[(v = ConstantArray[#3, Length@v]; f) &,
Append[l, Range@Length@l[]]]];


Your example (note last entry is names of variables to be realized):

imt[#1*i + #2*j, {{a, b, c}, {e, f, g}}, {i, j}]
(* {a + e, 2 b + 2 f, 3 c + 3 g} *)