Clojure deep-update-in

July 7, 2012 § Leave a Comment

I needed this the other day and wondered if it would help others or if there’s a better way.

There are two functions. The first goes looking for a key anywhere in a map and produces a sequence of key-paths that can be used with get-in, update-in and assoc-in. Note this code only recurses into substructures that are vectors or maps.

(defn find-key [ks k m]
  (cond (map? m)
        (reduce into (map (partial conj ks) (filter #{k} (keys m)))
                (map #(find-key (conj ks (key %)) k (val %)) m))
        (vector? m)
        (reduce into '() (map #(find-key (conj ks %1) k %2)
                              (iterate inc 0) m))))

The deep-update-in uses the above:

(defn deep-update-in [m k f]
  (reduce #(update-in %1 %2 f) m (find-key [] k m)))

m is the map, k the leaf key you're looking for (a single key, not a path of keys), and f the function you want to do the update.

What’s this?

You are currently reading Clojure deep-update-in at Pithering About.