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[[1]] &, Thread[Plus[##]]] &[{a, b, c}, {e, f, g}]
MapIndexed[# #2[[1]] &, +## & @@@ ({##}\[Transpose])] &[{a, b, c}, {e, f, g}]
MapIndexed[+(## & @@ # ) #2[[1]] &, #\[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 ? Apr 15, 2015 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. Apr 15, 2015 at 19:23
• @penguin77 it is a small world :)
– kglr
Apr 15, 2015 at 19:24
• @Mr.Wizard, good point, thank you. Updated with something that works with general two-arg functions.
– kglr
Apr 15, 2015 at 19:57
• Now you get my vote. :-) Apr 15, 2015 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, 2015 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[
#[[1]]*#2[[1]] + #[[2]]*#2[[1]] &,
{{a, b, c}, {e, f, g}}\[Transpose]
]

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


Here #[[1]] is the first element, #[[2]] is the second element, and #2[[1]] 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 Apr 15, 2015 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 :-) Apr 15, 2015 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. Apr 15, 2015 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. Apr 15, 2015 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. Apr 15, 2015 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[[1]];
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}

list = {{a, b, c}, {e, f, g}};


If the length of the list elements is known:

Transpose[list] * Range[3] // MapApply[Plus]


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

Otherwise

Transpose[list] * Range[Length @ First @ list] // MapApply[Plus]


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

Using MapThread:

F = MapThread[Total@*Times, {Transpose@#, Range[Last@Dimensions@#]}] &;

F@{{a, b, c}, {e, f, g}} // RepeatedTiming

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


Also, using MapIndexed:

F = MapIndexed[Total[#1*#2[[1]]] &, Transpose@#] &;

F@{{a, b, c}, {e, f, g}} // RepeatedTiming

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


As pointed out in a comment by @eldo (and thanks!)

MapThread[Plus,{{a,b,c},{e,f,g}}] Range[3]//Expand

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


Also

MapThread[Plus]@MapIndexed[#2[[2]]  #1&,{{a,b,c},{e,f,g}},{2}]

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


MapThread[Plus[#1,#2] &,{{a,b,c},{e,f,g}}] Range[3]//Expand

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

• +1. but MapThread[Plus, {{a, b, c}, {e, f, g}}] * Range[3] would be sufficient
– eldo
Oct 9, 2023 at 21:32

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[[1]]]]];


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