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

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.