(defn update-values [m f & args]The code is concise, but perhaps a bit terse. Still, it does the trick, as the REPL session below demonstrates.
(reduce (fn [r [k v]] (assoc r k (apply f v args))) {} m))
Clojure 1.2.0The last example is the specific problem I was looking to solve: remove a key-value pair from all the values of a map. However, the map I was working with actually had a bit of nesting. Let's define an example map that is similar to what I was actually working with.
user=> (defn update-values [m f & args]
(reduce (fn [r [k v]] (assoc r k (apply f v args))) {} m))
#'user/update-values
user=> (update-values {:a 1 :b 2 :c 3} inc)
{:c 4, :b 3, :a 2}
user=> (update-values {:a 1 :b 2 :c 3} + 10)
{:c 13, :b 12, :a 11}
user=> (update-values {:a {:z 1} :b {:z 1} :c {:z 1}} dissoc :z)
{:c {}, :b {}, :a {}}
user=> (def data {:boxes {"jay" {:linux 2 :win 1} "mike" {:linux 2 :win 2}}})Easy enough, I have 2 linux boxes and 1 windows box, and Mike has 2 linux and 2 windows. But, now the company decides to discard all of our windows boxes, and we'll need to update each user. A quick combo of update-in with update-values does the trick.
#'user/data
user=> (update-in data [:boxes] update-values dissoc :win)As you can see, the update-values function plays nice with existing Clojure functions as well.
{:boxes {"mike" {:linux 2}, "jay" {:linux 2}}}
Disclosure: I am long AAPL and own every device Apple puts out. Don't take my example numbers to literally. Also, much to my dismay, DRW has yet to discard all of our windows boxes.
Nice post. For variety's sake, here's another way to write update-values:
ReplyDelete(defn update-values [m f & args]
(into {} (for [[k v] m] [k (apply f v args)])))
@scgilardi - cool. thanks.
ReplyDeleteFor more variety:
ReplyDelete(defn update-values [m f & args] (zipmap (keys m) (map #(apply f % args) (vals m))))
(clojure.generic.functor/fmap {:a 1 :b 2} * 3) => {:a 3 :b 6}
ReplyDelete@ordnungswidrig is that going in core for 1.3? Sorry... I have to admit that I don't follow the bleeding edge...
ReplyDelete