我无法找到解决以下问题的方法:
假设我有一张地图:
(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]))
(可能有更好的方法......)但我希望更多的动态函数具有以下属性:
conj
带有右向量矢量的向量(如果当然存在相应的键)感谢您的帮助:)
答案 0 :(得分:24)
你一定要看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))
答案 1 :(得分:0)
这是这种功能的可能实现。这至少是一个起点,您可能需要一些额外的验证,具体取决于您的数据的可能结构(例如,如果覆盖地图的值是矢量但默认地图中的值甚至不是集合?)。
(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"}