【问题标题】:Merge two complex data structures合并两个复杂的数据结构
【发布时间】:2013-06-27 03:29:11
【问题描述】:

我无法找到以下问题的解决方案:

假设我有一张地图:

(def defaults {
  :name    "John"
  :surname "Doe"
  :info    {:date-of-birth "01-01-1980"
            :registered    [{:type "newsletter" :name "breaking news" }]}
})

然后我传递了一个类似的结构化映射,但我想合并向量并覆盖其余的键:

(def new {
  :name    "Peter"
  :info    {:date-of-birth "11-01-1986"
            :registered    [{:type "alert" :name "mobile-alert" }]}
})

我想要这个结果:

 {:name    "Peter"
  :surname "Doe"
  :info    {:date-of-birth "11-01-1986"
            :registered    [{:type "newsletter" :name "breaking news" }
                            {:type "alert"      :name "mobile-alert" }]}}

现在我可以使用静态语法轻松做到这一点:

(reduce conj (get-in defaults [:info :registered]) (get-in new [:info :registered]))

(可能有更好的方法...)但我希望更多的是具有以下属性的动态函数:

  1. 在不知道结构的情况下保留两个映射中的所有键
  2. 使用右侧映射中的值更新任何键
  3. 如果一个key的val是一个vector,那么conj那个vector和右边map的vector(当然如果有合适的key存在的话)

提前感谢您的帮助:)

【问题讨论】:

    标签: clojure


    【解决方案1】:

    你绝对应该看看merge-with 函数。这是可能的实现:

    (defn deep-merge [a b]
      (merge-with (fn [x y]
                    (cond (map? y) (deep-merge x y) 
                          (vector? y) (concat x y) 
                          :else y)) 
                     a b))
    

    【讨论】:

    • 完美运行。我怀疑它与合并有关,但我无法弄清楚......干杯!
    【解决方案2】:

    这是此类功能的可能实现。这至少是一个起点,您可能需要一些额外的验证,具体取决于数据的可能结构(例如,如果覆盖地图的值是向量但默认地图中的值甚至不是集合怎么办?)。

    (declare merge-maps)
    
    (defn merge-map [x [k v]]
      (cond (vector? v)
              (assoc x k (vec (reduce conj (x k) v)))
            (map? v)
              (assoc x k (merge-maps (x k) v))
            :esle
              (assoc x k v)))
    
    (defn merge-maps [x y]
      (reduce merge-map x y))
    
    (merge-maps defaults new)
    
    ;= {:info {:date-of-birth "11-01-1986", 
    ;=         :registered [{:name "breaking news", :type "newsletter"} 
    ;=                      {:name "mobile-alert", :type "alert"}]}, 
    ;=  :name "Peter", 
    ;=  :surname "Doe"}
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-15
      • 2021-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多