Performance 以更快/更惯用的方式实现;何时映射;?
我想实现一个函数,它映射一系列映射,并在谓词匹配时更新值 这是第一份工作草案:Performance 以更快/更惯用的方式实现;何时映射;?,performance,clojure,Performance,Clojure,我想实现一个函数,它映射一系列映射,并在谓词匹配时更新值 这是第一份工作草案: (defn update-if ([m k pred f] (let [init (get m k)] (if (and (not-nil? init) (pred init)) (update m k f) m))) ([m bindings] (reduce-kv (fn [agg k v] (let [[pred
(defn update-if
([m k pred f]
(let [init (get m k)]
(if (and (not-nil? init) (pred init))
(update m k f)
m)))
([m bindings]
(reduce-kv
(fn [agg k v]
(let [[pred f] v]
(update-if agg k pred f)))
m bindings)))
(update-if {:a 1 :b 2} {:a [even? inc] :b [even? dec]}) ;; ==> {:a 1 :b 1}
(update-if {:a 1 :b 2} :b even? dec) ;; ==> {:a 1 :b 1}
(defn map-when
"Walks a collection of associative collections
and applies functions based on predicates
Output :
(map-when {:a [even? inc] :b [nan? zero]} '({:a 1 :b NaN} {:a 2 :b 7} {:a 4 :b NaN}))
=
({:a 1 :b 0} {:a 3 :b 7} {:a 5 :b 0})"
([bindings data]
(reduce
(fn [acc row]
(conj acc (update-if row bindings)))
'() data))
([pred f data]
(map
(fn [x]
(if (and (not-nil? x) (pred x))
(f x)
x))
data)))
不是零吗?检查(这里)很重要,因为它只意味着数据丢失。
该函数在100万个随机{:a:b}
贴图(包括随机生成)上执行此操作大约需要2秒
我觉得奇怪的是,在核心/核心相关库中没有这个函数。
是否有一些性能提示可以改进这一点?我尝试了transient,但它在空列表上不起作用。'()
谢谢你应该这么做。它可能有你想要的东西。例如:
(def data {:a [{:aa 1 :bb 2}
{:cc 3}]
:b [{:dd 4}]})
;; Manual Clojure
(defn map-vals [m afn]
(->> m (map (fn [[k v]] [k (afn v)])) (into {})))
(map-vals data
(fn [v]
(mapv
(fn [m]
(map-vals
m
(fn [v] (if (even? v) (inc v) v))))
v)))
;; Specter
(transform [MAP-VALS ALL MAP-VALS even?] inc data)
你应该。它可能有你想要的东西。例如:
(def data {:a [{:aa 1 :bb 2}
{:cc 3}]
:b [{:dd 4}]})
;; Manual Clojure
(defn map-vals [m afn]
(->> m (map (fn [[k v]] [k (afn v)])) (into {})))
(map-vals data
(fn [v]
(mapv
(fn [m]
(map-vals
m
(fn [v] (if (even? v) (inc v) v))))
v)))
;; Specter
(transform [MAP-VALS ALL MAP-VALS even?] inc data)
仅生成必要的lambda以最大限度地提高可重用性
(defn cond-update-fn [clauses]
(fn [m]
(reduce (fn [m [k [pred f]]]
(cond-> m
(and (contains? m k)
(pred (get m k))) (update k f)))
m
clauses)))
如果您的pred和fn在编译时已知,那么编写宏(留给读者作为练习)可以提供更高的性能,因为没有pred迭代开销
在任何上下文中重用:
(def input [{:a 42, :b 42} {:a 42,:b 43}])
(def cond-update
(cond-update-fn {:a [even? inc]
:b [odd? dec]}))
(map cond-update input)
;-> ({:a 43, :b 42} {:a 43, :b 42})
;; Transducer
(into [] (map cond-update) input)
;-> [{:a 43, :b 42} {:a 43, :b 42}]
;; Standalone
(cond-update {:a 32})
;-> {:a 33}
仅生成必要的lambda以最大限度地提高可重用性
(defn cond-update-fn [clauses]
(fn [m]
(reduce (fn [m [k [pred f]]]
(cond-> m
(and (contains? m k)
(pred (get m k))) (update k f)))
m
clauses)))
如果您的pred和fn在编译时已知,那么编写宏(留给读者作为练习)可以提供更高的性能,因为没有pred迭代开销
在任何上下文中重用:
(def input [{:a 42, :b 42} {:a 42,:b 43}])
(def cond-update
(cond-update-fn {:a [even? inc]
:b [odd? dec]}))
(map cond-update input)
;-> ({:a 43, :b 42} {:a 43, :b 42})
;; Transducer
(into [] (map cond-update) input)
;-> [{:a 43, :b 42} {:a 43, :b 42}]
;; Standalone
(cond-update {:a 32})
;-> {:a 33}