Clojure 从深度嵌套贴图中删除nil值
根据这张地图:Clojure 从深度嵌套贴图中删除nil值,clojure,Clojure,根据这张地图: {:a nil :b {:c nil :d 2 :e {:f nil :g 4}}} 我需要一个函数来删除所有的nil值,以便返回的映射是 {:b {:e {:g 4} :d 2}} 或者,如果给出: {:a nil :b {:c nil :d nil :e {:f nil :g nil}}} 结果是: nil 有一个答案,其中包含一个
{:a nil
:b {:c nil
:d 2
:e {:f nil
:g 4}}}
我需要一个函数来删除所有的nil值,以便返回的映射是
{:b {:e {:g 4}
:d 2}}
或者,如果给出:
{:a nil
:b {:c nil
:d nil
:e {:f nil
:g nil}}}
结果是:
nil
有一个答案,其中包含一个假定适用于嵌套映射的函数,但当给定一个嵌套深度超过一级的映射时,该函数将失败。从此处修改答案
使用specter,您可以这样做:
(declarepath DEEP-MAP-VALS)
(providepath DEEP-MAP-VALS (if-path map? [(compact MAP-VALS) DEEP-MAP-VALS] STAY))
(setval [DEEP-MAP-VALS nil?] NONE
{:a nil
:b {:c nil
:d 2
:e {:f nil
:g 4}}})
请注意,如果没有剩余内容,它将返回:com.rpl.specter.impl/NONE
,而不是nil
这是对答案的部分重用,您可以通过
(remove(comp nil?second)el)
更改(filter#(second%)el)
来处理false
值,例如{:a nil:b false}
将返回{:b false}
@AbbéRésina,如果nil
值很少,修改地图比重建地图更快:(让[m(应用dissoc el(地图优先(过滤(comp-nil?second)el))))…)
感谢您的更正和建议。我已修复代码,只删除无值映射项。这不会保留记录,除非您使用(and(not(record?el))(map?el))
。当然,然后您接受不会删除记录的nil值。
(defn clean [m]
(if (map? m)
(let [clean-val (fn [[k v]]
(let [v' (clean v)]
(when-not (nil? v')
[k v'])))
m' (->> (map clean-val m)
(remove nil?)
(into {}))]
(when-not (empty? m') m'))
m))
(declarepath DEEP-MAP-VALS)
(providepath DEEP-MAP-VALS (if-path map? [(compact MAP-VALS) DEEP-MAP-VALS] STAY))
(setval [DEEP-MAP-VALS nil?] NONE
{:a nil
:b {:c nil
:d 2
:e {:f nil
:g 4}}})