How to write a dissoc-in command for clojure?

How about:

(defn dissoc-in
  "Dissociates an entry from a nested associative structure returning a new
  nested structure. keys is a sequence of keys. Any empty maps that result
  will not be present in the new structure."
  [m [k & ks :as keys]]
  (if ks
    (if-let [nextmap (get m k)]
      (let [newmap (dissoc-in nextmap ks)]
        (if (seq newmap)
          (assoc m k newmap)
          (dissoc m k)))
      m)
    (dissoc m k)))

Example:

(dissoc-in {:a {:b 0 :c 1}} [:a :b])

Result:

{:a {:c 1}}

dissoc-in was once part of clojure.contrib.core, and is now part of core.incubator.


If you want to keep empty maps, you can alter the code slightly:

(defn dissoc-in
  [m [k & ks :as keys]]
  (if ks
    (if-let [nextmap (get m k)]
      (let [newmap (dissoc-in nextmap ks)]
        (assoc m k newmap))
      m)
    (dissoc m k)))

Example:

(dissoc-in {:a {:b {:c 0}}} [:a :b])

Result:

{:a {}}

I write this using update-in:

(update-in {:a {:b 0 :c 1}} [:a] dissoc :b)

=>

{:a {:c 1}}

Tags:

Clojure