How can I transform a map based on the key? E.g.
(let [key->xf {:a inc, :b :dec}]
(S/transform [?] key->xf {:a 10, :b 20, :c 30}))
=> {:a 11, :b 19, :c 30}
I suspect I can use view
or transformed
for this, but not sure how. I found a FIND-KEYS
navigator on SO that navigates to the values of matching keys, but it isn’t quite what I’m looking for:
(def FIND-KEYS
"Like clojure.walk/postwalk but for Specter.
Use as [FIND-KEYS (S/must :key)]."
(S/recursive-path [] p
(S/cond-path map?
(S/continue-then-stay [S/MAP-VALS p])
vector? [S/ALL p]
S/STAY)))
E.g.
(S/select [FIND-KEYS (S/must :c)] {:a 123 :b {:c 456}})
=> 456
I guess I can do it with a plain-old reduce-kv, but hoping I could do it with Specter:
(defn transform-map
[mappings m]
(reduce-kv
(fn [acc k vf]
(if (contains? acc k)
(update acc k vf)
acc)) m mappings))
(transform-map {:a inc, :b dec} {:a 10, :b 20})
=> {:a 11, :b 19}
(def key->xf {:a inc :b dec :c identity})
(s/transform [s/ALL] (fn [entry] (let [[k v] entry] [k ((k key->xf) v)])) {:a 10, :b 20, :c 30})
=> {:a 11, :b 19, :c 30}
(`ALL` gives you key/value pairs in a vec)