Meet my little friend mapmap
I seem to chronically run into cases where I want to create a map in Clojure but don’t have just the right tool at hand. One nice function that I’ve found to be helpful is my little friend mapmap. mapmap is probably not a very good name – I’m open to suggestions. Maybe mapmerge would be better. It’s kind of a weird mix of zipmap, merge, and mapcat.
Here’s the code:
(defn mapmap
"Apply kf and vf to a sequence, s, and produce a map of (kf %) to (vf %)."
([vf s]
(mapmap identity vf s))
([kf vf s]
(zipmap (map kf s)
(map vf s))))
This function takes a sequence, and in the three-arg form applies a key function to the sequence, a value function to the values, and zips them together as a map. In the two-arg form, identity is used as the key function so the keys are the original sequence.
Two-arg example:
user> (mapmap #(* 10 %) [1 2 3 4 5])
{5 50, 4 40, 3 30, 2 20, 1 10}
user> (mapmap born-in [ "Chuck Berry" "Ted Nugent" ])
{"Ted Nugent" "Detroit", "Chuck Berry" "St. Louis"}
Three-arg example:
user> (mapmap #(+ 1 %) #(* 10 %) [1 2 3 4])
{5 40, 4 30, 3 20, 2 10}
And I’ve found it useful to use mapmap over a map as a sequence of map entries, for example to take a map and manipulate either the keys and/or the values of the map.
user> (mapmap #(subs (key %) 0 2)
(comp name val)
{ "abcd" :x, "foobar" :y, "nachos" :z })
{"na" "z", "fo" "y", "ab" "x"}
Or if for example you wanted to swap the keys and values in a map:
user> (mapmap val key { :a 1 :b 2 :c 3 })
{3 :c 2 :b 1 :a}
What do you think?

Hi! My name is Alex Miller and I live in St. Louis. I write code for a living and currently work for
Good post! Inspired me to a generic “Map-mapping” function:
http://gist.github.com/596728
Just happened across an example of where mapmap could be used inside clojure core in the protocol implementation:
(defn- emit-impl [[p fs]]
[p (zipmap (map #(-> % first keyword) fs)
(map #(cons 'fn (drop 1 %)) fs))])
The zipmap over two maps on the same sequence makes mapmap a perfect choice here:
(defn- emit-impl [[p fs]]
[p (mapmap #(-> % first keyword)
#(cons 'fn (drop 1 %))
fs)])
What do you think about making mapmap two different functions to improve the naming and usage?
(defn map-keys
“transform a map by applying a function to its keys
and \”dragging along\” its values. the transformation
function must be one-to-one for the keys of the map
and its range or else the resulting map would have more than
one value for a key”
[f m]
(zipmap (map f (keys m)) (vals m)))
(defn map-vals
“transform a map by applying a function to its values, keeping the
keys the same.”
[f m]
(zipmap (keys m) (map f (vals m))))
It also immediately suggests these functions.
(defn filter-keys
“makes a new map which contains only pairs for which
the filter function on the key of the pair returns true.
Preserves whatever meta-data the original map had.”
[fun m]
(select-keys m (filter fun (keys m))))
(defn filter-vals
“makes a new map which contains only pairs for which
the filter function on the value of the pair returns true.
Preserves whatever meta-data the original map had.”
[fun m]
(into {} (filter (comp fun val) m)))