从深层嵌套的地图中删除nil值

时间:2015-03-31 06:38:09

标签: clojure

鉴于此地图:

{:a nil 
   :b {:c nil 
       :d 2 
       :e {:f nil 
           :g 4}}}

我需要一个函数来删除所有的nil值,以便返回的map是

{:b {:e {:g 4}
     :d 2}}

或者,当给出时:

{:a nil 
   :b {:c nil 
       :d nil 
       :e {:f nil 
           :g nil}}}

结果是:

nil

This question有一个答案,其中包含一个可能适用于嵌套地图的函数,但是当给定一个嵌套深度超过一级的地图时,该函数会失败。

3 个答案:

答案 0 :(得分:7)

从这里修改答案https://stackoverflow.com/a/22186735/1393248


(defn remove-nils
  "remove pairs of key-value that has nil value from a (possibly nested) map. also transform map to nil if all of its value are nil" 
  [nm]
  (clojure.walk/postwalk 
   (fn [el]
     (if (map? el)
       (let [m (into {} (remove (comp nil? second) el))]
         (when (seq m)
           m))
       el))
   nm))

答案 1 :(得分:1)

(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))

答案 2 :(得分:0)

使用幽灵,您可以这样做:

(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

这是this答案的部分重用