How to "flatten" a nested Association?

Another idea:

FixedPoint[Association[Normal[#] /. Rule[n_, m_Association] :>
               KeyMap[Append[n, #] &, m]] &, KeyMap[{#} &, asso]]
<|{"fff", "2001", 5040.} -> {"S20010037", "S20010038", "S20010039",
   "S20010040", "S20010041", "S20010042"}, {"fff", "2005", 
   4350.} -> {"S20050448", "S20050449"}, {"fff", "2005", 
   3450.} -> {"S20050998", "S20050999"}|>

Which is the same as:

Association[Normal[KeyMap[List, asso]] //.
 (n_ -> m_Association) :> Normal[KeyMap[Append[n, #] &, m]]]

I think this works:

fn[a_ -> _[b__Rule]]  := Flatten[{a, #}] -> #2 & @@@ {b}
fn[x : (_ -> _fn) ..] := Flatten[fn /@ {x}]
fn[a_Association]     := <|a /. Association -> fn|>

Test:

fn[input]   (* input being your input expression *)
<|{"fff", "2001", 5040.} -> {"S20010037", "S20010038", "S20010039", "S20010040", 
   "S20010041", "S20010042"},
  {"fff", "2005", 4350.} -> {"S20050448", "S20050449"},
  {"fff", "2005", 3450.} -> {"S20050998", "S20050999"}|>

Perhaps cleaner:

ClearAll[fn]

a_ -> fn[b__] ^:= Flatten[{a, #}] -> #2 & @@@ Flatten[{b}]
fn[a_Association] := a /. Association -> fn
fn[x_List] := <|x|>

I feel as though there should be a simpler form than this but it eludes me at the moment.


asso = <|"fff" -> <|
    "2001" -> <|
      5040.` -> {"S20010037", "S20010038", "S20010039", "S20010040", 
        "S20010041", "S20010042"}|>, 
    "2005" -> <|4350.` -> {"S20050448", "S20050449"}, 
      3450.` -> {"S20050998", "S20050999"}|>|>|>

Ugly but working:

flatten = Association @* Flatten @* KeyValueMap[
   If[ MatchQ[#2, _Association], 
       flatten @ KeyMap[
          Function[key, If[MatchQ[#, {_, __}], Append[#, key], {#, key}]], 
          #2
       ], 
       # -> #2
   ] &
]

f @ asso
<|
 {"fff", "2001", 5040.} -> {"S20010037", "S20010038", "S20010039",    "S20010040", "S20010041", "S20010042"}, 
 {"fff", "2005", 4350.} -> {"S20050448", "S20050449"}, 
 {"fff", "2005",3450.} -> {"S20050998", "S20050999"}
|>

Tags:

Associations