Here is an approach that doesn't need to flatten the whole tree of data.
Let's take the example of moving the level 1 keys at the level 3, on the data assoc
of your self-answer :
assoc = Fold[AssociationThread[#2 -> #1] &, "X",
Reverse@Table[ToString[10 i + j], {i, 4}, {j, 2}]]
Here is a function showAssocListTree
that will be usefull to show clearly how associations are nested. It's just a formatting function. It is useless to understand it:
showAssocListTree = RightComposition[
# //. List[content___] :> Prepend[List1 /@ List1[content], "List"] &
, # /. List1 -> List &
, # //. as : Association[___] :>
Prepend[List @@@ Normal[as], "Ass."] &
, TableForm[#] &
, ToBoxes
, # //. GridBox[{{"\"List\"", ___}, r___}, r01___] :>
RowBox[{RotationBox[
StyleBox["\"List\"", FontVariations -> {"Underline" -> True}],
BoxRotation -> Pi/2], "["(*StyleBox["[",FontWeight\[Rule]
"Bold"]*), GridBox[{r}, r01]}] &
, # //. GridBox[{{"\"Ass.\"", ___}, r___}, r01___] :>
RowBox[{"-> ", RotationBox["\"Ass.\"", BoxRotation -> Pi/2],
StyleBox["[", FontWeight -> "Bold"], GridBox[{r}, r01]}] &
, # /. RowBox[{"-> ", r___}] :> RowBox[{r}] &
, # //. InterpretationBox[x_, ___] :> x &
, # /. RowBox[{a___, RotationBox["\"Ass.\"", BoxRotation -> Pi/2],
r___}] :>
RowBox[{a, RotationBox["\"Association\"", BoxRotation -> Pi/2],
r}] &
, RawBoxes
, Style[#, GridBoxOptions -> { GridBoxDividers -> None},
SpanMaxSize -> DirectedInfinity[1]] &
];
your data formatted :
assoc // showAssocListTree
Insertion of level 1 data at level 3 :
listOfAssoc=KeyValueMap[
Function[{k, v}, Map[Association[k -> #] &, v, {2}]], assoc];
listOfAssoc //showAssocListTree
Note that the outer Association
has been transformed in a List
.
Now, the built-in function Merge
will be applied. This function only merge two successive levels. So, a recursive function is first created. Note that when applied, this recursive function will explode exponentially, but in most cases, it's better than to flatten the whole tree, and there are probably ways to circumvent this problem.
ClearAll[myMerge]
myMerge[x : {_Association ..}] := Merge[x, myMerge]
myMerge[{x_}] := x
myMerge[listOfAssoc ] //showAssocListTree
This approach can be generalised to the general case. For example {3, 1, 4, 2} could be decomposed as {1, 2, 3, 4} -> {1, 3, 4, 2} -> {3, 1, 4, 2}
inspiration source