12
$\begingroup$

According to the documentation, MapThread works on Association objects. But it doesn't seem to evaluate the passed function. For example:

MapThread[#1 + #2 &, {<|a -> 1, b -> 2|>, <|a -> 5, b -> 6|>}]

returns:

<|a -> (#1 + #2 &)[1, 5], b -> (#1 + #2 &)[2, 6]|>

I would have expected <| a -> 6, b -> 8 |>.

$\endgroup$
5
  • 1
    $\begingroup$ Evaluate /@ MapThread[Plus, ...] ? $\endgroup$
    – unlikely
    Oct 16, 2014 at 8:12
  • $\begingroup$ It seems to work if the Associations are in separate Lists: MapThread[#1 + #2 &, {{<|a -> 1, b -> 2|>}, {<|a -> 5, b -> 6|>}}] $\endgroup$
    – RunnyKine
    Oct 16, 2014 at 8:27
  • $\begingroup$ @RunnyKine I think that is merely accomplishing <|a -> 1, b -> 2|> + <|a -> 5, b -> 6|>. (Which itself is of interest however.) $\endgroup$
    – Mr.Wizard
    Oct 16, 2014 at 8:37
  • $\begingroup$ @Mr.Wizard. Indeed. $\endgroup$
    – RunnyKine
    Oct 16, 2014 at 8:41
  • 2
    $\begingroup$ I vote for bug... $\endgroup$
    – Rojo
    Oct 16, 2014 at 19:25

4 Answers 4

4
$\begingroup$

Evaluation with Association is at present poorly defined (IMO). See: Held keys in associations. Your example shows that MapThread does work on associations but the RHS fails to evaluate. Map causes the elements to evaluate:

MapThread[# + #2 &, {<|a -> 1, b -> 2|>, <|a -> 5, b -> 6|>}]

Identity /@ %
<|a -> (#1 + #2 &)[1, 5], b -> (#1 + #2 &)[2, 6]|>

<|a -> 6, b -> 8|>

Since there appears to be confusion with regard to the function of some different proposals in other answers and comments I feel it needs to be pointed out that several of them work by simply evaluating:

<|a -> 1, b -> 2|> + <|a -> 5, b -> 6|>

Which somewhat surprisingly yields:

<|a -> 6, b -> 8|>

As I cannot recall seeing this in the documentation I asked:

$\endgroup$
4
$\begingroup$

Not an answer... some observations:

Activate/@MapThread[(#+#2)&, {<|a -> 1, b -> 2|>, <|a -> 5, b -> 6|>}]
Normal@MapThread[(#+#2)&,{<|a -> 1, b -> 2|>, <|a -> 5, b -> 6|>}]
ReleaseHold/@MapThread[(#+#2)&, {<|a -> 1, b -> 2|>, <|a -> 5, b -> 6|>}]
Evaluate/@MapThread[(#+#2)&, {<|a -> 1, b -> 2|>, <|a -> 5, b -> 6|>}]
MapThread[(#+#2)&,{<|a -> 1, b -> 2|>, <|a -> 5, b -> 6|>}, 0]

all give

<|a -> 6, b -> 8|>

and, as noted by Mr. Wizard, all are equivalent to,

<|a -> 1, b -> 2|> + <|a -> 5, b -> 6|>

$\endgroup$
5
  • $\begingroup$ +1 but realize that only Map is important here; e.g. Evaluate is incidental. $\endgroup$
    – Mr.Wizard
    Oct 16, 2014 at 8:45
  • $\begingroup$ In your example using Thread, Thread is superfluous; you are merely adding the two associations which triggers automatic threading. Likewise the use of MapThread with levelspec 0. See eldo's deleted answer and my just-posed question on the subject. $\endgroup$
    – Mr.Wizard
    Oct 16, 2014 at 8:55
  • $\begingroup$ @Mr.W got it ... finally ... thanks:) $\endgroup$
    – kglr
    Oct 16, 2014 at 9:07
  • $\begingroup$ One down, one to go. (grin) Now realize that MapThread[(# + #2) &, {x, y}, 0] is merely x + y. $\endgroup$
    – Mr.Wizard
    Oct 16, 2014 at 9:09
  • $\begingroup$ Mr.W it is indeed... $\endgroup$
    – kglr
    Oct 16, 2014 at 9:10
4
$\begingroup$

It works with V 13.3 (and maybe with some versions preceding it)

data = {<|a -> 1, b -> 2|>, <|a -> 5, b -> 6|>}

MapThread[#1 + #2 &, data]

<|a -> 6, b -> 8|>

MapThread[Plus, data]

<|a -> 6, b -> 8|>

But this fails without warnings:

MapThread[Total] @ data

<|a -> 1, b -> 2|>

Anyway, I think one should use Merge, which was specifically designed to work with Lists of Rules and Associations.

Merge[Total] @ data

<|a -> 6, b -> 8|>

Merge[Apply @ Plus] @ data

<|a -> 6, b -> 8|>

$\endgroup$
1
  • 1
    $\begingroup$ (+1) Also MapThread[Total[{##}]&, {<|a -> 1, b -> 2|>, <|a -> 5, b -> 6|>}] $\endgroup$
    – user1066
    Sep 16, 2023 at 15:37
1
$\begingroup$

It seems that the resulting association from your code is unevaluated.

In=  MapThread[#1 + #2 &, {<|a -> 1, b -> 2|>, <|a -> 5, b -> 6|>}]
Out= <|a -> (#1 + #2 &)[1, 5], b -> (#1 + #2 &)[2, 6]|>
In=  %[a]
Out= 6

I think you can do it by

Merge[{<|a -> 1, b -> 2|>, <|a -> 5, b -> 6|>}, Total]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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