1
$\begingroup$

I have the following three lists:

kr = {{8, 8, 19, 3, 3}, {8, 8, 21, 3, 3}, {8, 8, 23, 3, 3}};
Rk = {{8., 3, 4, 5, 6}, {8., 4, 5, 6, 7}, {8., 5, 6, 7, 8}};
qsum = {{320, 270, 120, 140, 170}, {320, 280, 120, 150, 190}, {320, 290, 120, 160, 210}}; 

When I use

MapThread[#1 + #2 + #3 &, {Take[#, {3, -2}] & /@ kr, Take[#, {4, -1}] & /@ Rk, Take[#, {3, -2}] & /@ qsum}]

It shows the output {{144., 149.}, {147., 160.}, {150., 171.}}

which is perfectly fine, but using the function floExct in the MapThread as

floExct[n_, ku_, qr_] := Min[100*ku, (2500*n) - qr];
MapThread[ floExct[#1, #2, #3] &, {Take[#, {3, -2}] & /@ kr, Take[#, {4, -1}] & /@ Rk, Take[#, {3, -2}] & /@ qsum}]

gives me

{500., 600., 700.}

instead of the format

{{a,b},{c,d},{e,f}};

What am I missing?

$\endgroup$
8
  • $\begingroup$ You are aware that the function Min returns a single scalar value? $\endgroup$ Apr 4 '14 at 17:02
  • $\begingroup$ I understand that the function floExct will return 1 value, but it should be evaluated 6 times and needs to give 6 values. $\endgroup$
    – brama
    Apr 4 '14 at 17:04
  • $\begingroup$ The dimensions of the list MapThread is being applied to is {3,3,2}, so you would expect only three results. $\endgroup$ Apr 4 '14 at 17:14
  • $\begingroup$ Take[#, {3, -2}] & /@ kr->{{19, 3}, {21, 3}, {23, 3}}, Take[#, {4, -1}] & /@ Rk->{{5, 6}, {6, 7}, {7, 8}} and Take[#, {3, -2}] & /@ qsum->{{120, 140}, {120, 150}, {120, 160}} so I would expect the result to be in the {{a,b},{c,d},{e,f}} format $\endgroup$
    – brama
    Apr 4 '14 at 17:21
  • 2
    $\begingroup$ Try this MapThread[floExct, {Take[#, {3, -2}] & /@ kr, Take[#, {4, -1}] & /@ Rk, Take[#, {3, -2}] & /@ qsum}, 2] $\endgroup$
    – Aky
    Apr 4 '14 at 17:31
2
$\begingroup$

As was initially mentioned in the comments, you can use the levelspec argument of MapThread to get the behavior you were expecting, but you can also set your floExct function to have the Listable attribute. This is why Plus works well for your first example snippet.

In[11]:= floExct[n_, ku_, qr_] := Min[100*ku, (2500*n) - qr];
SetAttributes[floExct, Listable];
MapThread[
 floExct[#1, #2, #3] &, {Take[#, {3, -2}] & /@ kr, 
  Take[#, {4, -1}] & /@ Rk, Take[#, {3, -2}] & /@ qsum}]

Out[13]= {{500, 600}, {600, 700}, {700, 800}}
$\endgroup$
1
  • $\begingroup$ Thanks for the answer and the neat trick to make custom functions as listable. $\endgroup$
    – brama
    Apr 8 '14 at 17:48
1
$\begingroup$

I suppose it wouldn't hurt to add a bit of explanation here.

Plus is Listable, which is why Plus[{a, b}, {c, d}] evaluates to {Plus[a, c], Plus[b, d]} (it automatically threads over lists in its arguments). In fact, you did not need to use MapThread at all:

Plus[Take[#, {3, -2}] & /@ kr, Take[#, {4, -1}] & /@ Rk, 
 Take[#, {3, -2}] & /@ qsum] (* {{144, 149}, {147, 160}, {150, 171}} *)

On the other hand, Min flattens any lists in its arguments, eg. Min[{a, b}, {c, d}] evaluates to Min[a, b, c, d], not {Min[a, c], Min[b, d]}

Now, generally speaking, MapThread[func, {{p1, q1}, {p2, q2}}] == {func[p1, p2], func[q1, q2]}

Consider that p1, p2, q1 and q2 could themselves be lists, eg. p1 = {a1, b1}, p2 = {a2, b2}, q1 = {m1, n1}, q2 = {m2, n2}; The third argument of MapThread determines at which level of the list you want the threading to happen.

With the levelspec = 1 (default), MapThread[func, {{p1, q1}, {p2, q2}}] == {func[{a1, b1}, {a2, b2}], func[{m1, n1}, {m2, n2}]}, mentally replacing func with Min (and recalling its flattening behaviour) explains why the output isn't what you desire.

OTOH, MapThread[func, {{p1, q1}, {p2, q2}}, 2], which is the same as MapThread[func, {{{a1, b1}, {m1, n1}}, {{a2, b2}, {m2, n2}}}, 2], evaluates to {{func[a1, a2], func[b1, b2]}, {func[m1, m2], func[n1, n2]}}. If you mentally replace func with Min (or your floExct) you'll see this is the expression you want.

I'm afraid I haven't been able to express myself clearly (perhaps someone could polish it?), but hopefully the reader will be able to connect any missing links.

$\endgroup$
1
  • $\begingroup$ Got it...Thanks. $\endgroup$
    – brama
    Apr 8 '14 at 17:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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