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$
1
  • $\begingroup$ You could also use Association /@ rather than Apply[Association]@* in your code with same results. $\endgroup$
    – MarcoB
    Jul 30, 2017 at 22:54

3 Answers 3

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$
1
  • $\begingroup$ It avoids referencing the association twice, so it's definitely better than the original. $\endgroup$ Jul 30, 2017 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$
5
  • $\begingroup$ Kuba, is NestedMerge a new function? It's not documented, or do you mean Nest[Merge,f,n] $\endgroup$ Aug 3, 2017 at 21:26
  • $\begingroup$ @alancalvitti I linked it, click it :) $\endgroup$
    – Kuba
    Aug 3, 2017 at 21:38
  • $\begingroup$ my fault, I thought false highlighting. What are the advantages of NestedMerge viz Nest[Merge,...]? $\endgroup$ Aug 3, 2017 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$ Aug 3, 2017 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, 2017 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 and acknowledge you have read our privacy policy.

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