【问题标题】:Filter nil values from Clojure map?从 Clojure 映射中过滤 nil 值?
【发布时间】:2012-03-09 13:01:37
【问题描述】:

从 Clojure 映射 {} 中过滤 nil 值的最佳方法是什么?

{ :a :x :b nil :c :z }
;;=>  { :a :x, :c :z }

【问题讨论】:

    标签: map filter clojure


    【解决方案1】:

    我会使用:

    (into {} (filter (comp some? val) {:a :x, :b nil, :c :z}))
    
    => {:a :x, :c :z}
    

    明确地执行some? 检查很重要,因为如果您只执行(into {} (filter val {...})),那么您将错误地删除布尔值为假的值。

    【讨论】:

    • 或者(into {} (remove (comp nil? val) {:a :x :b nil :c :z}))
    • 是的,删除版本是等效的。实际上,在 Clojure 源码中 remove 实际上是使用 filter 实现的,如:(filter (complement pred) coll)。带过滤器的版本稍微快一点,带删除的版本稍微短一点:-)
    • 嵌套的 nil 值怎么样?
    【解决方案2】:

    我使用以下代码:

    (into {} (filter val {:a 1, :b 2, :c nil}))
    ;;=> {:a 1, :b 2}
    

    注意:这将删除错误值以及 nils

    【讨论】:

    • 这也过滤了错误:(
    • 你可以使用 mikera 描述的方法。但在大多数情况下,我们的逻辑是 nil 表示 false 和 vv
    【解决方案3】:

    可能不是最好的解决方案,但这是使用列表理解的解决方案:

    (into {} 
      (for [[k v] {:a 1 :b nil :c :z} :when (not (nil? v))]
        [k v]))
    

    【讨论】:

      【解决方案4】:
      (into {} (keep (fn [e] (if (val e) e)) {:a :x :b nil :c :z}))
      ;;=> {:a :x, :c :z}
      

      或者更短一点:

      (into {} (keep #(if (val %) %) {:a :x :b nil :c :z}))
      

      事实上,你的过滤器建议更好更短,所以我会使用它:

      (into {} (filter val {:a :x :b nil :c :z}))
      

      【讨论】:

      • 你的函数返回 (:x :z) 而不是 {:a :x :c :z}
      【解决方案5】:

      这样做最好的方法实际上是(into {} (keep second {:a :x :b nil}))

      【讨论】:

      • (keep second {:a :x :b nil}) ==> (:x), into 抛出异常。
      猜你喜欢
      • 2011-11-04
      • 1970-01-01
      • 2016-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-02
      • 1970-01-01
      • 2012-08-04
      相关资源
      最近更新 更多