Mapping a function on the values of a map in Clojure

I want to transform one map of values to another map with the same keys but with a function applied to the values. I would think there was a function for doing this in the clojure api, but I have been unable to find it.

Here's an example implementation of what I'm looking for

(defn map-function-on-map-vals [m f]
  (reduce (fn [altered-map [k v]] (assoc altered-map k (f v))) {} m))
(println (map-function-on-map-vals {:a "test" :b "testing"} #(.toUpperCase %)))
{:b TESTING, :a TEST}

Does anybody know if map-function-on-map-vals already exists? I would think it did (probably with a nicer name too).


Solution 1:

I like your reduce version just fine. I think it's idiomatic. Here's a version using list comprehension anyways.

(defn foo [m f]
  (into {} (for [[k v] m] [k (f v)])))

Solution 2:

You can use the clojure.algo.generic.functor/fmap:

user=> (use '[clojure.algo.generic.functor :only (fmap)])
nil
user=> (fmap inc {:a 1 :b 3 :c 5})
{:a 2, :b 4, :c 6}

Solution 3:

Here is a fairly typical way to transform a map. zipmap takes a list of keys and a list of values and "does the right thing" producing a new Clojure map. You could also put the map around the keys to change them, or both.

(zipmap (keys data) (map #(do-stuff %) (vals data)))

or to wrap it up in your function:

(defn map-function-on-map-vals [m f]
    (zipmap (keys m) (map f (vals m))))

Solution 4:

Taken from the Clojure Cookbook, there is reduce-kv:

(defn map-kv [m f]
  (reduce-kv #(assoc %1 %2 (f %3)) {} m))

Solution 5:

Here's a fairly idiomatic way to do this:

(defn map-function-on-map-vals [m f]
        (apply merge
               (map (fn [[k v]] {k (f v)})
                    m)))

Example:

user> (map-function-on-map-vals {1 1, 2 2, 3 3} inc))
{3 4, 2 3, 1 2}