# Reduction of nested association based on criteria

I have a nested association of the following form:

test = <|
"key1" -> <|"key11" -> 11, "key12" -> 12, "key13" -> 13|>,
"key2" -> <|0 -> <|"X" -> 5, "Y" -> 0|>, 1 -> <|"X" -> 6, "Y" -> 0|>,2 -> <|"X" -> 7, "Y" -> 0|>,3 -> <|"X" -> 8, "Y" -> 0|>|>,
"key3" -> <|"key31" -> 31, "key32" -> 32, "key33" -> 33|>
|>


"key2" refers to measurement points 0,1,2,3 each with an x- and y-value referable by "X" and "Y". Now I want to reduce the whole nested association test to a form, which only contains the measurement points with x>6. So the output should be:

test2 = <|
"key1" -> <|"key11" -> 11, "key12" -> 12, "key13" -> 13|>,
"key2" -> <|2 -> <|"X" -> 7, "Y" -> 0|>,3 -> <|"X" -> 8, "Y" -> 0|>|>,
"key3" -> <|"key31" -> 31, "key32" -> 32, "key33" -> 33|>
|>


Is there a convenient way to do so, that means without rebuilding the whole nested association? I tried alot using Delete, Select and Datset, but could not find any solution.

• I guess you mean, you want to reduce it to key-value pairs that have X>6 or don't have X at all? May 22, 2021 at 14:47
• No, I want to maintain the nested association with all points with x<=6 dropped from it. The aim is to achieve an output like test2 gives in my question.
– Sven
May 22, 2021 at 15:05
• MapAt[Cases[#, x_ /; x["X"] > 6, {1}] &, test, "key2"] ? May 22, 2021 at 15:28

If we can rely upon the target associations always being under "key2" and always having a subkey "X", then:

test // MapAt[Select[#X > 6 &], "key2"]

% === test2
(* True *)


or

test // Query[{"key2" -> Select[#X > 6 &]}]


In a more general case where we do not know the parent key or even if the subvalues are necessarily associations, then:

DeleteCases[test, KeyValuePattern[{"X" -> x_ /; x <= 6}], {2}]


If we know neither the parent key nor even the level of the target associations, then::

DeleteCases[test, KeyValuePattern[{"X" -> x_ /; x <= 6}], Infinity]

• Great, thank you very much! Very elegant solutions.
– Sven
May 23, 2021 at 12:35
test = <|"key1" -> <|"key11" -> 11, "key12" -> 12, "key13" -> 13|>,
"key2" -> <|0 -> <|"X" -> 5, "Y" -> 0|>, 1 -> <|"X" -> 6, "Y" -> 0|>,
2 -> <|"X" -> 7, "Y" -> 0|>, 3 -> <|"X" -> 8, "Y" -> 0|>|>,
"key3" -> <|"key31" -> 31, "key32" -> 32, "key33" -> 33|>|>;
keepkeys2 = Position[test["key2"], x_ /; x["X"] > 6]
keepvals2 = Extract[test["key2"], keepkeys2]