【问题标题】:Clojure deep-merge to ignore nil valuesClojure 深度合并以忽略 nil 值
【发布时间】:2014-11-25 15:44:02
【问题描述】:

我正在尝试在 Clojure 中深度合并多个地图。我在网上找到了很多解决方案,其中大部分看起来像:

(defn deep-merge
  [& xs]
 (if (every? map? xs)
   (apply merge-with deep-merge xs)
  (last xs)))

这个解决方案的问题是,如果其中一个映射为 nil,它将删除所有之前的映射(因此如果最后一个映射为 nil,则整个函数将返回 nil)。在常规合并函数中情况并非如此,它忽略了 nil 值。 是否有其他容易实现忽略 nil 值的深度合并?

【问题讨论】:

    标签: clojure merge null


    【解决方案1】:

    我在:https://github.com/circleci/frontend/blob/04701bd314731b6e2a75c40085d13471b696c939/src-cljs/frontend/utils.cljs 找到了这个。它做的正是它应该做的。

    (defn deep-merge* [& maps]
      (let [f (fn [old new]
                 (if (and (map? old) (map? new))
                     (merge-with deep-merge* old new)
                     new))]
        (if (every? map? maps)
          (apply merge-with f maps)
         (last maps))))
    
    (defn deep-merge [& maps]
      (let [maps (filter identity maps)]
        (assert (every? map? maps))
       (apply merge-with deep-merge* maps)))
    

    感谢 CircleCi 人!

    【讨论】:

    • 对于后代来说,这似乎是最初在 clojure.contrib 中的一种变体,并且从未收到维护者,因此从未进入 clojure.core。可以在这里找到问题和原始代码的链接:dev.clojure.org/jira/browse/CLJ-1468
    【解决方案2】:

    立即删除nils?

    (defn deep-merge [& xs]
      (let [xs (remove nil? xs)]
        (if (every? map? xs)
          (apply merge-with deep-merge xs)
          (last xs))))
    

    【讨论】:

    • 不幸的是,这仍然没有提供与合并相同的行为。在“nil”值的情况下,merge 会考虑该值,但您的实现不会。例如: (merge {:a 3} {:a nil}) => {:a nil} ,但是 (deep-merge {:a 3} {:a nil}) => {:a 3}
    • @Asher 我认为这个问题需要澄清。它指出常规合并函数忽略 nil 值。您现在说 merge 考虑了该值。该问题要求轻松实现忽略 nil 值的深度合并,而不是与合并具有相同的行为。一两个例子可能会有所帮助。当然,我接受这个解决方案不是您想要的。
    • 我将解释不同之处:如果要合并的 maps 之一为 nil,则 merge 将忽略它。但是,如果地图中的 values 之一为 nil,则合并不会忽略它。案例 1 的示例:(合并 {:a 1} nil {:b 2})=> {:a 1 :b 2}。案例 2 示例: (merge {:a 1} {:a nil} {:b 2}) => {:a nil :b 2}
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-13
    • 1970-01-01
    • 2021-05-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多