Multiple Dissoc child keys on a map?

How can I do a search and split multiple child keys.

Example:

(def d {:foo 123
        :bar {
          :baz 456
          :bam {
            :whiz 789}}})

(dissoc-descendents d [:foo :bam])
;->> {:bar {:baz 456}}
+5
source share
2 answers

clojure.walk is useful in such situations:

(use 'clojure.walk)
(postwalk #(if (map? %) (dissoc % :foo :bam) %) d)
+6
source

If you want to implement it directly, I would suggest something like the following:

(defn dissoc-descendents [coll descendents]
  (let [descendents (if (set? descendents) descendents (set descendents))]
    (if (associative? coll)
      (reduce
        (fn [m [k v]] (if (descendents k) 
                        (dissoc m k)
                        (let [new-val (dissoc-descendents v descendents)]
                          (if (identical? new-val v) m (assoc m k new-val)))))
        coll
        coll)
      coll)))

Key points to consider when implementing:

  • It makes sense to convert the descendants into a set: this will allow you to quickly check membership if the set of deleted keys is large
  • There is some logic to ensure that if the value does not change, you do not need to change this part of the map. This is a pretty big performance gain if large areas of the map have not changed.
+1
source

All Articles