Search code examples
vectorclojurehashmap

dissoc a key in a vector of hashmaps in a cond->


How do I remove :z of data inside a cond-> ?

(def data
  {:a [{:x 1
        :y 2
        :z "remove this"}
       {:x 3
        :y 4
        :z 5}]
   :b "b"
   :c "c"})

I suspect I'll have to used update-in, but I have not been having success.

(cond-> data
        :a (#(<function to remove :z when :z is "remove this">))
        :b (dissoc :b))

My current theory is to use update-in, map, and an if statement. I have not been able to find the exact syntax that works, though

(cond-> data
        :a (#(update-in (:a %) [:z]
                        (map (fn [A]
                               (if (= (:z A) "remove this")
                                 (dissoc A :z)
                                 A))
                             (:a %))))
        :b (dissoc :b))
=> ClassCastException clojure.lang.LazySeq cannot be cast to clojure.lang.IFn  clojure.core/apply (core.clj:652) 

Solution

  • Your attempt there is very close:

    You seem to do navigate twice "into" the map. If you want to change the items of :a in that map, then update is enough. Also you don't have to path via :z, since this is the one you want to dissoc from the map.

    So my suggestion here is:

    (cond-> data
      :a (update :a
                 (partial mapv #(if (= (:z %) "remove this") (dissoc % :z) %)))
      :b (dissoc :b))
    
    • update because we change only the top level
    • remember, the first param to update comes from cond->
    • mapv to keep the vector
    • the first param to the function passed to update will be (:a data), but mapv takes this as last argument - so use partial here
    • this leaves us with the option to use the function literal as mapping function (remember, no nesting of function literals); of course this function is a candidate to extract into its own function