Skip to content

Instantly share code, notes, and snippets.

@fogus
Last active August 10, 2021 20:25
Show Gist options
  • Save fogus/436146a8b4a6871dcce424c33e6d4a3c to your computer and use it in GitHub Desktop.
Save fogus/436146a8b4a6871dcce424c33e6d4a3c to your computer and use it in GitHub Desktop.
(defn update-keys-naive
"m f => {(f k) v ...}
Given a map m and a function f of 1-argument, returns a new map whose
keys are the result of applying f to the keys of m, mapped to the
corresponding values of m.
f must return a unique key for each key of m."
{:added "1.11"}
[m f]
(let [ret (with-meta
(zipmap (map f (keys m)) (vals m))
(meta m))]
(if (= (count m) (count ret))
ret
(throw (RuntimeException. "Key transform function did not return unique values.")))))
(defn update-vals-naive
"m f => {k (f v) ...}
Given a map m and a function f of 1-argument, returns a new map where the keys of m
are mapped to result of applying f to the corresponding values of m."
{:added "1.11"}
[m f]
(with-meta
(zipmap (keys m) (map f (vals m)))
(meta m)))
(defn update-keys-red
"reduce, assumes seq of Map.Entry, builds [[k v]...] as input to into"
{:added "1.11"}
[m f]
(let [ret (into (with-meta {} (meta m))
(reduce
(fn [acc ^java.util.Map$Entry me] (conj acc [(f (.getKey me)) (.getValue me)]))
[]
m))]
(if (= (count m) (count ret))
ret
(throw (RuntimeException. "Key transform function did not return unique values.")))))
(defn update-vals-red
"reduce, assumes seq of Map.Entry, calls out to update"
{:added "1.11"}
[m f]
(with-meta
(reduce
(fn [acc ^java.util.Map$Entry me] (update acc (.getKey me) f))
m
m)
(meta m)))
(defn update-keys-rkv
"reduce-kv, builds [[k v]...] as input to into"
{:added "1.11"}
[m f]
(into (with-meta {} (meta m))
(reduce-kv (fn [acc k v] (conj acc [(f k) v]))
[]
m)))
(defn update-vals-rkv
"reduce-kv calls out to update"
{:added "1.11"}
[m f]
(reduce-kv (fn [acc k _] (update acc k f))
m
m))
(defn update-keys-trns
"Transducer version, builds [[k v]...] as input to into"
{:added "1.11"}
[m f]
(let [ret (into (with-meta {} (meta m))
(map (fn [[k v]] [(f k) v]))
m)]
(if (= (count m) (count ret))
ret
(throw (RuntimeException. "Key transform function did not return unique values.")))))
(defn update-vals-trns
"Transducer version, builds [[k v]...] as input to into"
{:added "1.11"}
[m f]
(into (with-meta {} (meta m))
(map (fn [[k v]] [k (f v)]))
m))
;;; reduce-kv2
(defn reduce-kv2
([f init coll]
(if (instance? clojure.lang.IKVReduce coll)
(.kvreduce coll f init)
(clojure.core.protocols/kv-reduce coll f init))))
(defn update-keys-rkv2
"reduce-kv, builds [[k v]...] as input to into"
{:added "1.11"}
[m f]
(into (with-meta {} (meta m))
(reduce-kv2 (fn [acc k v] (conj acc [(f k) v]))
[]
m)))
(defn update-vals-rkv2
"reduce-kv calls out to update"
{:added "1.11"}
[m f]
(reduce-kv2 (fn [acc k _] (update acc k f))
m
m))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment