4
$\begingroup$

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.

$\endgroup$
3
  • $\begingroup$ I guess you mean, you want to reduce it to key-value pairs that have X>6 or don't have X at all? $\endgroup$ – Carl Lange May 22 at 14:47
  • $\begingroup$ 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. $\endgroup$ – Sven May 22 at 15:05
  • 1
    $\begingroup$ MapAt[Cases[#, x_ /; x["X"] > 6, {1}] &, test, "key2"] ? $\endgroup$ – Ben Izd May 22 at 15:28
3
$\begingroup$

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]
$\endgroup$
1
  • $\begingroup$ Great, thank you very much! Very elegant solutions. $\endgroup$ – Sven May 23 at 12:35
4
$\begingroup$
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]
new2 = AssociationThread[Flatten@keepkeys2, keepvals2]
ReplacePart[test, "key2" -> new2]
$\endgroup$
3
  • $\begingroup$ Great! Small error. First keepkeys should not be keepkeys2 $\endgroup$ – FredrikD May 22 at 16:50
  • $\begingroup$ @FredrikD Fixed. $\endgroup$ – Alan May 22 at 17:24
  • $\begingroup$ Thanks for your solution. Works fine! $\endgroup$ – Sven May 23 at 12:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.