Take the 2-minute tour ×
Mathematica Stack Exchange is a question and answer site for users of Mathematica. It's 100% free, no registration required.

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.

share|improve this question

3 Answers 3

up vote 14 down vote accepted

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
share|improve this answer
    
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 <|#, ...|>. –  jtbandes Jul 14 at 3:44
    
Actually...is that even documented? –  jtbandes Jul 14 at 4:06

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|> *)
share|improve this answer

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|>

share|improve this answer
    
It's cool that functions like ^ work on the association's values. –  jtbandes Jul 14 at 3:45

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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