11
$\begingroup$

I have an association that maps {x, y} pairs to values, for example:

 <|{0, 0} -> "a", {-1, -4} -> "b", {-1, 1} -> "c", {-1, 0} -> "d", {1, 0} -> "e"|>

I want to convert this to a nested association with the outer association keyed by x and the inner by y:

<|0 -> <|0 -> "a"|>, -1 -> <|-4 -> "b", 0 -> "d", 1 -> "c"|>, 1 -> <|0 -> "e"|>|>

My current code is (assuming a is the association):

Apply[Association]@*Map[Last@# -> a[#] &] /@ GroupBy[Keys@a, First, Sort]

but I'm wondering if there's a more elegant way to do this (sorting not necessary).

$\endgroup$
  • $\begingroup$ You could also use Association /@ rather than Apply[Association]@* in your code with same results. $\endgroup$ – MarcoB Jul 30 '17 at 22:54
8
$\begingroup$

The following will do the same thing and avoid the sorting, but I am not sure whether it counts as "more elegant" in your book:

assoc = <|{0, 0} -> "a", {-1, -4} -> "b", {-1, 1} -> "c", {-1, 0} -> "d", {1, 0} -> "e"|>;

Association /@
 GroupBy[#[[1, 1]]& -> (#[[1, 2]] -> #[[2]] &)]@
  Normal@assoc

(*Out:  <|0 -> <|0 -> "a"|>, -1 -> <|-4 -> "b", 1 -> "c", 0 -> "d"|>, 1 -> <|0 -> "e"|>|> *)
$\endgroup$
  • $\begingroup$ It avoids referencing the association twice, so it's definitely better than the original. $\endgroup$ – 2012rcampion Jul 30 '17 at 23:57
7
$\begingroup$
Merge[
    KeyValueMap[ #[[1]] -> <|#[[2]] -> #2|> &, asso]
  , Association
]
<|0 -> <|0 -> "a"|>, -1 -> <|-4 -> "b", 1 -> "c", 0 -> "d"|>,  1 -> <|0 -> "e"|>|>

For deeper examples {1,2,3,4,1}->"a" etc, you may need MergeNested

$\endgroup$
  • $\begingroup$ Kuba, is NestedMerge a new function? It's not documented, or do you mean Nest[Merge,f,n] $\endgroup$ – alancalvitti Aug 3 '17 at 21:26
  • $\begingroup$ @alancalvitti I linked it, click it :) $\endgroup$ – Kuba Aug 3 '17 at 21:38
  • $\begingroup$ my fault, I thought false highlighting. What are the advantages of NestedMerge viz Nest[Merge,...]? $\endgroup$ – alancalvitti Aug 3 '17 at 21:49
  • $\begingroup$ Btw, can you email me re WTC this year if you're going - re planned get together in C-U or Chi? Your contact info lists gluonvision but only Rolf's email shows up there. $\endgroup$ – alancalvitti Aug 3 '17 at 21:54
  • 1
    $\begingroup$ @alancalvitti due to personal matters I can't go this year. Would love to meet fellow MMA users again but maybe next year. $\endgroup$ – Kuba Aug 3 '17 at 22:05
1
$\begingroup$
keyTrie=Query[keyGroupBy[First]]/*Query[All,KeyMap[Rest]]/*Query[All,If[Keys[#1]=={{}},First[Values[#1]],keyTrie[#1]]&]

This is a recursive query that uses keyGroupBy utility:

keyGroupBy[f_][expr_]:=Association/@GroupBy[Normal[expr],Keys/*f]

To your data:

<|{0, 0} -> "a", {-1, -4} -> "b", {-1, 1} -> "c", {-1, 0} -> 
   "d", {1, 0} -> "e"|> // keyTrie

<|0 -> <|0 -> "a"|>, -1 -> <|-4 -> "b", 1 -> "c", 0 -> "d"|>, 1 -> <|0 -> "e"|>|>

$\endgroup$

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.