5

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!

creidhne
  • 5,055
  • 4
  • 20
  • 28

2 Answers2

4

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|>|>

vindobona
  • 3,241
  • 1
  • 11
  • 19
  • 1
    Thank you! That seems to work! Not sure what limitations / assumptions there are, but it might suffice for my code! Thanks again! – Stefan Gillessen Jan 27 '24 at 14:00
2
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|>|>

eldo
  • 67,911
  • 5
  • 60
  • 168