This page is not created by, affiliated with, or supported by Slack Technologies, Inc.
2020-10-07
Channels
- # announcements (9)
- # beginners (155)
- # bristol-clojurians (1)
- # calva (49)
- # chlorine-clover (36)
- # cider (10)
- # clara (6)
- # clj-kondo (14)
- # clojars (28)
- # clojure (226)
- # clojure-australia (1)
- # clojure-berlin (12)
- # clojure-czech (1)
- # clojure-europe (26)
- # clojure-germany (1)
- # clojure-nl (2)
- # clojure-uk (32)
- # clojurescript (9)
- # conjure (21)
- # datascript (3)
- # datomic (43)
- # emacs (3)
- # figwheel-main (16)
- # fulcro (17)
- # graalvm (9)
- # helix (4)
- # lambdaisland (3)
- # malli (13)
- # off-topic (12)
- # pathom (7)
- # re-frame (10)
- # reitit (9)
- # rewrite-clj (2)
- # shadow-cljs (41)
- # spacemacs (6)
- # specter (3)
- # test-check (5)
- # tools-deps (9)
- # tree-sitter (1)
- # vim (15)
- # xtdb (3)
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)