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

Reply via email to