I have a reference to a vector [] that has maps added to it. If I want to change the value of a map item based on a predicate matching, what is the idiomatic way to do that?
For example...
[ { :id 1 :name "Joe" } { :id 2 :name "Fred" } ]
And we want to update any id of 2 to the name 'Brian'.
Here's one way:
(def people [ { :id 1 :name "Joe" } { :id 2 :name "Fred" } ])
(defn brian-converter [person]
(if (= 2 (:id person))
(assoc person :name "Brian")
person))
(map brian-converter people)
;;=> ({:id 1, :name "Joe"} {:id 2, :name "Brian"})
Depending on how you expect those values to change, you might prefer something more flexible:
(defn create-converter [[key-to-match val-to-match]
key-to-replace val-to-replace]
(fn [person]
(if (= val-to-match (key-to-match person))
(assoc person key-to-replace val-to-replace)
person)))
(map (create-converter [:id 2] :name "Brian") people)
;;=> ({:id 1, :name "Joe"} {:id 2, :name "Brian"})
(map (create-converter [:id 1] :name "Dude") people)
;;=> ({:id 1, :name "Dude"} {:id 2, :name "Fred"})
The choice of argument representation (vector for the search params, unrolled arguments for the replacements) in create-converter
was kind of arbitrary for me; not sure if there's a rule for that.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With