# Association Subtotals with Lists as Keys

I have the following Association:

as = <|{5, 2, 1} -> 3, {6, 1, 4} -> 9, {5, 1, 9} -> 12, {5, 2, 4} -> 6, {6, 2, 8} -> 10|>;


I want to total the values on the right side of the rules according to the middle values of the keys to get

<|2 -> 19, 1 -> 21|>

The only way I know how to do this is to transform the Association to a List:

li = as /. (Association | Rule) -> List


{{{5, 2, 1}, 3}, {{6, 1, 4}, 9}, {{5, 1, 9}, 12}, {{5, 2, 4}, 6}, {{6, 2, 8}, 10}}

li = GatherBy[li /. {{_, a_, _}, b_} :> {a, b}, First]


{{{2, 3}, {2, 6}, {2, 10}}, {{1, 9}, {1, 12}}}

Association @ MapThread[Rule, {Map[#[[1, 1]] &, li], Total /@ Map[Last, li, {2}]}]


<|2 -> 19, 1 -> 21|>

Is there a way to get this result without destroying the Association ?

Solutions based on GroupBy can be made a bit simpler by exploiting the fact that as itself can be used as a function, and I like the aesthetics of the curried form of Extract, where Extract[{2}] is equivalent to Extract[#, {2}]&:

In[1]:= GroupBy[Keys[as], Extract[{2}] -> as, Total]
Out[1]= <|2 -> 19, 1 -> 21|>

• Impressive! How does the  Extract[{2}] -> as work?
– eldo
Oct 31, 2015 at 19:00
• First Keys gets all the keys from as, then you can Extract the second element from each key. This gives you the association <|2 -> {{5, 2, 1}, {5, 2, 4}, {6, 2, 8}}, 1 -> {{6, 1, 4}, {5, 1, 9}}|>, where GroupBy has already collected all the keys that share a common second element. The →as part effectively tells GroupBy to go back to the original association and treat the collected lists as keys (again), replacing {5,2,1} with 3, {6,1,4} with 9 and so on. Oct 31, 2015 at 21:15

GroupBy[KeyValueMap[#[[2]] -> #2 &, as], First -> Last, Total]


<|2 -> 19, 1 -> 21|>

Or shorter, per @Kuba:

Merge[Total]@KeyValueMap[#[[2]] -> #2 &, as]

• Merge[Total] will be shorter. I'm not sure if KeyValueMap fits since it destroys association.
– Kuba
Oct 31, 2015 at 18:32
• @Kuba Does it technically destroy the association? Or just map over the keys?
– kale
Oct 31, 2015 at 18:35
• I have Version 10.0 which doesn't know KeyValueMap
– eldo
Oct 31, 2015 at 18:35
• @eldo Oops, introduced in 10.1...
– kale
Oct 31, 2015 at 18:37
• @Kuba, ah, you're right. KeyValueMap returns a list for some insane reason.
– kale
Oct 31, 2015 at 18:40

Not so compact

GroupBy[AssociationMap[Reverse][as], #[[2]] &, Total @* Keys]

• It would be nice to have some kind of third argument for KeyMap to specify type of Merging.
– Kuba
Oct 31, 2015 at 21:06