# Equivalent of ReplaceAll for Associations?

Is there a nice (built-in) way to apply Replace-style rules to key-value pairs in an association? Something like

SomeFunction[<| "id" -> 3, "freq" -> 4 |>, "freq" -> #freq+1 &]
(* should produce <| "id" -> 3, "freq" -> 5 |> *)


This could also be used to add computed keys, like

SomeFunction[..., "density" -> #mass / #volume &]


This would be really useful when combining with Query and Dataset.

Adding the same key to an Association will replace the previous value, which leads to this solution:

assoc = <| "id" -> 3, "freq" -> 4 |>;
<|#, "freq" -> #freq + 1|> &@assoc
(* <| "id" -> 3, "freq" -> 5 |> *)


The following alternatives also work:

assoc["freq"] = 5
assoc["freq"] = assoc["freq"] + 1
assoc["freq"] += 1

• Neat. The really interesting part of this isn't that adding a key replaces an existing one, but that you can merge by putting the whole association inside another like <|#, ...|>. Jul 14 '14 at 3:44
• Actually...is that even documented? Jul 14 '14 at 4:06
• It's as if Association had a Flat attribute. Jan 11 '15 at 21:18

You can use AssociateTo to change an existing Association which is already bound to a variable. The definition of your SomeFunction would then look like the following

SetAttributes[SomeFunction, {HoldFirst}];
SomeFunction[a_, func_] := AssociateTo[a, func[a]]


and you examples work like this

assoc=<|"id"->3,"freq"->4,"mass"->2,"volume"->5|>;
SomeFunction[assoc,"freq"->#freq+1&]
SomeFunction[assoc,"density"->#mass/#volume&]
(* <|id->3,freq->5,mass->2,volume->5|> *)
(* <|id->3,freq->5,mass->2,volume->5,density->2/5|> *)


You can also use KeySelect to operate on keys that meet certain criteria.

assoc = <|"id" -> 3, "freq" -> 4, "fred" -> 2, "geeze" -> 1|>;
endsInD = KeySelect[assoc, StringMatchQ[#, __ ~~ "d"] &]


<|"id" -> 3, "fred" -> 2|>

Merge[
{assoc, #^2 &@endsInD},
Last]


<|"id" -> 9, "freq" -> 4, "fred" -> 4, "geeze" -> 1|>

• It's cool that functions like ^ work on the association's values. Jul 14 '14 at 3:45