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.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

What’s this?

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