3
$\begingroup$

Consider for example the nested association:

myA = <|"d" -> <|"c" -> <|"a" -> 1, "b" -> 2|>|>|>

It is easy to map a function to a key on the first level:

MapAt["c" /. # &, myA, "d"]

enter image description here

but MapAt doesn't work with levels higher than 1

MapAt["a" /. # &, myA, "c"]

enter image description here

So I tried a workaround, trasforming all the associations to lists:

  Replace[
    myA /. Association -> ass
    ,
    Rule["c", x_] -> Rule["c", ("a" + "b") /. x], Infinity
  ] /. ass -> Association 

getting the correct result, but with some errors that I can't fix

enter image description here

I've tried with Hold, but it looks like it works at level 1 only.

Thank you for your help!

$\endgroup$
2
  • $\begingroup$ Do you need to extract a value or is this only an example of a function "c" /. # &? p.s. it would help to have desired results presented as it is not clear what is the ultimate goal. $\endgroup$
    – Kuba
    Commented Feb 10, 2020 at 11:49
  • $\begingroup$ MapAt["a" /. # &, myA, {All, "c"}]? $\endgroup$
    – kglr
    Commented Feb 10, 2020 at 12:34

1 Answer 1

6
$\begingroup$

Here is a function that finds all keys of a given name anywhere in your data structure and maps a function onto those positions:

mapAtKeyEveryWhere[assoc_, fun_, key_] := MapAt[
  fun,
  assoc,
  Append[Key[key]] /@ Position[
    assoc,
    KeyValuePattern[key -> _]
  ]
];

Test it:

myA = <|"d" -> <|"c" -> <|"a" -> 1, "b" -> 2|>|>|>;
mapAtKeyEveryWhere[myA, ("a" + "b") /. # &, "c"]
(* <|"d" -> <|"c" -> 3|>|> *)

Is that what you have in mind?

$\endgroup$
1
  • $\begingroup$ Perfect, thanks Sjoerd! $\endgroup$ Commented Feb 10, 2020 at 13:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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