""

# 156 Map Defaults

## Problem

When retrieving values from a map, you can specify default values in case the key is not found:

(= 2 (:foo {:bar 0, :baz 1} 2))

However, what if you want the map itself to contain the default values? Write a function which takes a default value and a sequence of keys and constructs a map.

## Solution

The test cases that I was given were:

``````(= (__ 0 [:a :b :c]) {:a 0 :b 0 :c 0})
test not run
(= (__ "x" [1 2 3]) {1 "x" 2 "x" 3 "x"})
test not run
(= (__ [:a :b] [:foo :bar]) {:foo [:a :b] :bar [:a :b]})``````

Right away I noticed that we need to ’do work’ on each item in the collection that’s passed into the function. This makes me think that `map` will be what I reach for.

Start with the first test case as it’s the simplest (in my mind) to think about. I personally like to define an anonymous function with `fn` since it makes the values you pass in explicit (vs the `#()` syntax).

This is where I’ll start:

``((fn [dv col] (map () col)) 0 [:a :b :c])``

`col` is passed into the `map` since we want to iterate over `[:a :b :c]`. I know I want to associate a key to a value when `map` visits each value in the collection. This is when we’ll reach for `assoc` as it does just that.

You’ll also notice that we are passing in the value that we want to use for each key - value pair as `dv`.

``((fn [dv col] (map (fn [key] (assoc {} key dv)) col)) 0 [:a :b :c])``

The function that is defined for our map takes in a value which we will use as the key in our resulting map. In that function we will tell `assoc` that we want a hash-map by passing in `{}`. Then we’ll set the key to `key` which is passed in from the map and we’ll set the value in that hash-map to `dv` which is accessible because the top level function is a closure.

The results are:

``{:a 0} {:b 0} {:c 0}``

This isn’t quite what we want since we have 3 separate hash-maps. That’s actually a decent fix because `merge` exists.

``((fn [dv col] (reduce merge (map (fn [key] (assoc {} key dv)) col))) 0 [:a :b :c])``

By using reduce with merge, we can combine the individual hash-maps into one large one. This passes the test case above!

``{:a 0 :b 0 :c 0}``

As it turns out, I implemented a naive version of `zipmap`.

• zipmap: Returns a map with the keys mapped to the corresponding vals.

A big part of learning clojure has been knowing what core functions are available to you. If you utilize zip map.. you can shorten the implementation by quite a bit

``((fn [dv col] (zipmap col (repeat dv))) 0 [:a :b :c])``

This produces the same results. If you want to get the best golf score possible, use shorthand like Ian Jones does.

``(#(zipmap %2 (repeat %1)) 0 [:a :b :c])``

### Notes mentioning this note

There are no notes linking to this note.