Trim 使用幽灵的深层嵌套数据结构中的不必要条目
Trim unnecessary entries from deeply nested data structure using specter
我希望使用 Clojure Spectre 来简化深度嵌套的数据结构。我要删除:
- 任何值为 nil 的条目
- 任何具有空字符串值的条目
- 任何具有空映射值的条目
- 任何具有空顺序值的条目
- 任何具有 maps/sequential 值的条目在删除上述情况后为空。
像这样:
(do-something
{:a {:aa 1}
:b {:ba -1
:bb 2
:bc nil
:bd ""
:be []
:bf {}
:bg {:ga nil}
:bh [nil]
:bi [{}]
:bj [{:ja nil}]}
:c nil
:d ""
:e []
:f {}
:g {:ga nil}
:h [nil]
:i [{}]
:j [{:ja nil}]})
=>
{:a {:aa 1}
:b {:ba -1
:bb 2}}
我在香草 Clojure 中有一些东西:
(defn prunable?
[v]
(if (sequential? v)
(keep identity v)
(or (nil? v) (#{"" [] {}} v))))
(defn- remove-nil-values
[ticket]
(clojure.walk/postwalk
(fn [el]
(if (map? el)
(let [m (into {} (remove (comp prunable? second) el))]
(when (seq m)
m))
el))
ticket))
我想我需要某种 recursive-path
但我进展不快。非常感谢帮助。
比较不同版本与 spectre 实现的性能:
@bm1729 原版:
Evaluation count : 1060560 in 60 samples of 17676 calls.
Execution time mean : 57.083226 µs
Execution time std-deviation : 543.184398 ns
Execution time lower quantile : 56.559237 µs ( 2.5%)
Execution time upper quantile : 58.519433 µs (97.5%)
Overhead used : 7.023993 ns
Found 5 outliers in 60 samples (8.3333 %)
low-severe 3 (5.0000 %)
low-mild 2 (3.3333 %)
Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
以下版本:
Evaluation count : 3621960 in 60 samples of 60366 calls.
Execution time mean : 16.606135 µs
Execution time std-deviation : 141.114975 ns
Execution time lower quantile : 16.481250 µs ( 2.5%)
Execution time upper quantile : 16.922734 µs (97.5%)
Overhead used : 7.023993 ns
Found 9 outliers in 60 samples (15.0000 %)
low-severe 6 (10.0000 %)
low-mild 3 (5.0000 %)
Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
(defn prune [x]
(cond
(map? x) (not-empty
(reduce-kv
(fn [s k v]
(let [v' (prune v)]
(cond-> s
v' (assoc k v'))))
(empty x)
x))
(seqable? x) (not-empty
(into
(empty x)
(->> x (map prune) (filter identity))))
:else x))
测试用例:
(prune {:a {:aa 1}
:b {:ba -1
:bb 2
:bc nil
:bd ""
:be []
:bf {}
:bg {:ga nil}
:bh [nil]
:bi [{}]
:bj [{:ja nil}]}
:c nil
:d ""
:e []
:f {}
:g {:ga nil}
:h [nil]
:i [{}]
:j [{:ja nil}]})
;; => {:b {:bb 2, :ba -1}, :a {:aa 1}}
更新 - @bm1729 幽灵版本
Evaluation count : 3314820 in 60 samples of 55247 calls.
Execution time mean : 18.421613 µs
Execution time std-deviation : 591.106243 ns
Execution time lower quantile : 18.148204 µs ( 2.5%)
Execution time upper quantile : 20.674292 µs (97.5%)
Overhead used : 7.065044 ns
Found 8 outliers in 60 samples (13.3333 %)
low-severe 2 (3.3333 %)
low-mild 6 (10.0000 %)
Variance from outliers : 18.9883 % Variance is moderately inflated by outliers
感谢 Clojurians slack 频道上的 nathanmarz
:
(def COMPACTED-VALS-PATH
(recursive-path [] p
(continue-then-stay
(cond-path
map? [(compact MAP-VALS) p]
vector? [(compact ALL) p]))))
(defn- compact-data
[m]
(setval [MAP-VALS COMPACTED-VALS-PATH #(or (nil? %) (= "" %))] NONE m))
我希望使用 Clojure Spectre 来简化深度嵌套的数据结构。我要删除:
- 任何值为 nil 的条目
- 任何具有空字符串值的条目
- 任何具有空映射值的条目
- 任何具有空顺序值的条目
- 任何具有 maps/sequential 值的条目在删除上述情况后为空。
像这样:
(do-something
{:a {:aa 1}
:b {:ba -1
:bb 2
:bc nil
:bd ""
:be []
:bf {}
:bg {:ga nil}
:bh [nil]
:bi [{}]
:bj [{:ja nil}]}
:c nil
:d ""
:e []
:f {}
:g {:ga nil}
:h [nil]
:i [{}]
:j [{:ja nil}]})
=>
{:a {:aa 1}
:b {:ba -1
:bb 2}}
我在香草 Clojure 中有一些东西:
(defn prunable?
[v]
(if (sequential? v)
(keep identity v)
(or (nil? v) (#{"" [] {}} v))))
(defn- remove-nil-values
[ticket]
(clojure.walk/postwalk
(fn [el]
(if (map? el)
(let [m (into {} (remove (comp prunable? second) el))]
(when (seq m)
m))
el))
ticket))
我想我需要某种 recursive-path
但我进展不快。非常感谢帮助。
比较不同版本与 spectre 实现的性能:
@bm1729 原版:
Evaluation count : 1060560 in 60 samples of 17676 calls.
Execution time mean : 57.083226 µs
Execution time std-deviation : 543.184398 ns
Execution time lower quantile : 56.559237 µs ( 2.5%)
Execution time upper quantile : 58.519433 µs (97.5%)
Overhead used : 7.023993 ns
Found 5 outliers in 60 samples (8.3333 %)
low-severe 3 (5.0000 %)
low-mild 2 (3.3333 %)
Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
以下版本:
Evaluation count : 3621960 in 60 samples of 60366 calls.
Execution time mean : 16.606135 µs
Execution time std-deviation : 141.114975 ns
Execution time lower quantile : 16.481250 µs ( 2.5%)
Execution time upper quantile : 16.922734 µs (97.5%)
Overhead used : 7.023993 ns
Found 9 outliers in 60 samples (15.0000 %)
low-severe 6 (10.0000 %)
low-mild 3 (5.0000 %)
Variance from outliers : 1.6389 % Variance is slightly inflated by outliers
(defn prune [x]
(cond
(map? x) (not-empty
(reduce-kv
(fn [s k v]
(let [v' (prune v)]
(cond-> s
v' (assoc k v'))))
(empty x)
x))
(seqable? x) (not-empty
(into
(empty x)
(->> x (map prune) (filter identity))))
:else x))
测试用例:
(prune {:a {:aa 1}
:b {:ba -1
:bb 2
:bc nil
:bd ""
:be []
:bf {}
:bg {:ga nil}
:bh [nil]
:bi [{}]
:bj [{:ja nil}]}
:c nil
:d ""
:e []
:f {}
:g {:ga nil}
:h [nil]
:i [{}]
:j [{:ja nil}]})
;; => {:b {:bb 2, :ba -1}, :a {:aa 1}}
更新 - @bm1729 幽灵版本
Evaluation count : 3314820 in 60 samples of 55247 calls.
Execution time mean : 18.421613 µs
Execution time std-deviation : 591.106243 ns
Execution time lower quantile : 18.148204 µs ( 2.5%)
Execution time upper quantile : 20.674292 µs (97.5%)
Overhead used : 7.065044 ns
Found 8 outliers in 60 samples (13.3333 %)
low-severe 2 (3.3333 %)
low-mild 6 (10.0000 %)
Variance from outliers : 18.9883 % Variance is moderately inflated by outliers
感谢 Clojurians slack 频道上的 nathanmarz
:
(def COMPACTED-VALS-PATH
(recursive-path [] p
(continue-then-stay
(cond-path
map? [(compact MAP-VALS) p]
vector? [(compact ALL) p]))))
(defn- compact-data
[m]
(setval [MAP-VALS COMPACTED-VALS-PATH #(or (nil? %) (= "" %))] NONE m))