5
$\begingroup$

Assume I have

ass = <|"A" -> 1, "B" -> <|"B1" -> 2, "B2" -> 3|>|>

I can flatten it to

<|"A" -> 1, {"B", "B1"} -> 2, {"B", "B2"} -> 3|>

via the hints in

How to "flatten" a nested Association?

However, how can I 'unflatten' it, i.e. do the reverse operation?

The associations can be arbitrarily long, could be nested also deeper than here, and contain also Lists or other data types as values. Further the same sub-keys might occur in different parts, for example a key "B2" could be present also in an association "C"-> . In other words, the structure should be as given by the Keys in the flattened version.

Thanks for any help!

$\endgroup$

2 Answers 2

5
$\begingroup$

Perhaps something like this:

unflattenAssociation = 
 ReplaceAll[Association[List[v__]] :> v]@
   Merge[Association]@
    KeyValueMap[If[! ListQ@#, <|Rule@##|>, Fold[<|#2 -> #|> &, #2, Reverse[#]]] &]@# &;


unflattenAssociation@<|"A" -> 1, {"B", "B1"} -> 2, {"B", "B2"} -> 3|>

<|"A" -> 1, "B" -> <|"B1" -> 2, "B2" -> 3|>|>

$\endgroup$
1
  • 1
    $\begingroup$ Thank you! That seems to work! Not sure what limitations / assumptions there are, but it might suffice for my code! Thanks again! $\endgroup$ Commented Jan 27 at 14:00
2
$\begingroup$
ass = <|"A" -> 1, {"B", "B1"} -> 2, {"B", "B2"} -> 3|>;

Even for this simple case my solution is complicated

Association @ ReplaceAll[{(a_ -> {b_, c_}) :> a -> <|b, c|>, {a_} :> a}] @ 
 Normal @ Merge[Identity] @
    ReplaceAll[({a_, b_} -> c_) :> a -> {b -> c}] @ Normal[ass]

<|"A" -> 1, "B" -> <|"B1" -> 2, "B2" -> 3|>|>

$\endgroup$
1
  • $\begingroup$ Thanks, but this obviously gets very ugly when I have A, B, C, D, E, ... and each of the sub-associations are longer, too ... $\endgroup$ Commented Jan 27 at 6:44

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