It's actually good to have default values for non-existing entries, as in Timothy's examples. Otherwise the previous version will throw NPEs. So:
(defn map-map ([f map] (map-map f map (keys map) nil)) ([f map keys] (map-map f map keys nil)) ([f map keys default] (reduce (fn [m k] (assoc m k (f (m k default)))) map keys))) On Jun 18, 5:06 pm, Rowdy Rednose <rowdy.redn...@gmx.net> wrote: > Thanks for the ideas guys > > I especially like the reduce/assoc approach. It's the one most clear > to me so far and also the most efficient one, I guess, as it does only > one assoc per changed key, without creating other intermediate maps. > > So this is what I ended up using, with the nice side-effect that I now > also have a reusable function: > > (defn map-map > ([f map] (map-map f map (keys map))) > ([f map keys] > (reduce (fn [m k] (assoc m k (f (m k)))) map keys))) > > (map-map inc map keys) > > It also happens to be 3 times as fast as my initial implementation, > using that small data set from my first post. > > On Jun 18, 2:41 pm, Timothy Pratley <timothyprat...@gmail.com> wrote: > > > Your version is already succinct, is there something you particularly > > don't like about it? > > > I would probabbly write it like this: > > (defn inc-values-in-map > > [map keys] > > (reduce #(assoc %1 %2 (inc (%1 %2 0))) map keys)) > > Because it caters better with (inc-values-in-map m > > [:one :three :one :four]) > > > Or more readably: > > (defn assoc-fn > > [f default] > > (fn [m k] > > (assoc m k (f (m k default)))) > > (defn inc-values-in-map > > [map keys] > > (reduce (assoc-fn inc 0) map keys)) > > > But its longer than yours :) > > > On Jun 18, 3:21 pm, Rowdy Rednose <rowdy.redn...@gmx.net> wrote: > > > > Say I've got this map of keys to integer values: > > > > (def m {:one 0 :two 0 :three 0}) > > > > I want to write a function "inc-values-in-map" that takes such a map, > > > a collection of keys and will increment those keys' values in the map. > > > > In other words, calling > > > > (inc-values-in-map m [:one :three]) > > > > should return > > > > {:one 1, :two 0, :three 1} > > > > I've come up with this: > > > > (defn inc-values-in-map > > > [map keys] > > > (merge-with + map (zipmap keys (repeat 1)))) > > > > Aren't there more elegant ways to implement this function? --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Clojure" group. To post to this group, send email to clojure@googlegroups.com Note that posts from new members are moderated - please be patient with your first post. To unsubscribe from this group, send email to clojure+unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/clojure?hl=en -~----------~----~----~----~------~----~------~--~---