# Make association with deepest rules from nested association

I want to extract only the deepest level of association in a nested associations.

An example of input data is

<|a -> 1, b -> <|x -> p, y -> <|z -> 3, w -> "a"|>|>|>


and I need to get

<|a -> 1, x -> p, z -> 3, w -> "a"|>


I have seen several questions similar to this but I have not been able to solve the problem.

What is the best way to do this?

Thanks!

test1 = <|a -> 1, b -> <|x -> p, y -> <|z -> 3, w -> "a"|>|>|>
Association[Level[test1 /. Association -> List, {-2}]]
(* <|a -> 1, x -> p, z -> 3, w -> "a"|> *)


Update

To address the comment about needing to handle the cases where the values of the lowest level associations might be lists...

test2 = <|a -> 1, b -> <|c -> 1, d -> {2, 3}|>|>
Association[Normal[test1] //. (_ -> val_Association) :> Splice[Normal[val]]]
(* <|a -> 1, x -> p, z -> 3, w -> "a"|> *)

Association[Normal[test2] //. (_ -> val_Association) :> Splice[Normal[val]]]
(* <|a -> 1, c -> 1, d -> {2, 3}|> *)


Probably want to bundle into a function:

AssociationLeaves[a_Association] :=
Association[Normal[a] //. (_ -> val_Association) :> Splice[Normal[val]]]

• Concise solution, thanks! Commented Oct 27, 2023 at 4:36
asc = <|a -> 1, b -> <|x -> p, y -> <|z -> 3, w -> "a"|>|>|>

asc /. Association -> List // Level[#, {-2}] & // Association


<|a -> 1, x -> p, z -> 3, w -> "a"|>

Or

Normal@asc //. {HoldPattern[a_ -> b_ /; ! AssociationQ[b]] :> a -> b,
HoldPattern[a_ -> b_ /; AssociationQ[b]] :> Normal@b} //
Flatten // Association


Result:

<|a -> 1, x -> p, z -> 3, w -> "a"|>

• Thanks! The latter example was a little difficult for me, but I think I understand it somehow. Commented Oct 27, 2023 at 4:38
• The latter seems necessary when the association contains lists as data. (ex) asc = <|a -> 1, b -> <|c -> 1, d -> {2, 3}|>|>; Commented Oct 27, 2023 at 4:51
flattenA // ClearAll
flattenA[a_Association]     := Association @ Flatten @ KeyValueMap[flattenA] @ a
flattenA[k_, v_Association] := KeyValueMap[flattenA] @ v;
flattenA[k_, v_]            := k -> v

flattenA@<|a -> 1, b -> <|x -> p, y -> <|z -> 3, w -> "a"|>|>|>


<|a -> 1, x -> p, z -> 3, w -> "a"|>

• This gives Association[ Flatten[KeyValueMap[flattenA][<|a -> 1, b -> <|x -> p, y -> <|z -> 3, w -> "a"|>|>|>]]].
– Syed
Commented Oct 27, 2023 at 6:59
• @Syed sorry, made a typo, corrected.
– Kuba
Commented Oct 27, 2023 at 7:25
asc = <|a -> 1, b -> <|x -> p, y -> <|z -> 3, w -> "a"|>|>|>;

NestWhile[
Association@
KeyValueMap[
If[AssociationQ@#2, #2, # -> #2] &, #] &, asc, UnsameQ, 2]

(* Output *)
<|a -> 1, x -> p, z -> 3, w -> "a"|>

• also FixedPoint[Association@*KeyValueMap[If[AssociationQ@#2, #2, # -> #2] &], asc] (+1)
– kglr
Commented Oct 28, 2023 at 17:51
• @kglr Nice one, thanks! Commented Oct 28, 2023 at 22:58
asc = <|a -> 1, b -> <|x -> p, y -> <|z -> 3, w -> "a"|>|>|>;


Using Fold and MapAt

Association @ Flatten @ Fold[
MapAt[Last, ##] &,
asc /. Association :> List,
{2, {2, 2}}]


<|a -> 1, x -> p, z -> 3, w -> "a"|>