雖與扁平化的辦法解決您的具體問題,這是不具有普遍性。根據你的問題,我猜你需要一個關鍵字地圖作爲結果向量。它的工作原理是,當所有的地圖都包含完全相同的密鑰時。但你猜以下極端案例:
user> (merge-with (comp flatten vector) {:a "b"})
;;=> {:a "b"} oops! you following processing probably wants {:a ["b"]}
user> (merge-with (comp flatten vector) {:a "b"} {:c "d"})
;;=> {:a "b", :c "d"} once again!
user> (merge-with (comp flatten vector) {:a ["b"]} {:a ["c" ["d"]]})
;;=> {:a ("b" "c" "d")}
;; here i can see some inconsistent behavior, breaking the initial data form: would't you rather want {:a [["b"] ["c" ["d"]]]} ?
如此,因爲你正在做的事情進行生產,而不是學習, 我會建議使用以下方法:你可以做的函數,合併地圖,而且處理出現在結果中的特殊方式單一(或第一)鍵:
(defn smart-merge-with [first-val-fn merge-fn & args]
(when (seq args)
(reduce (fn [acc items-map]
(reduce (fn [acc [k v]]
(if (contains? acc k)
(update acc k merge-fn v)
(assoc acc k (first-val-fn v))))
acc items-map))
{} args)))
現在你可以只是包裝的第一個值到一個載體,然後,當有另一個值具有相同的鍵出現只是將其添加到那個矢量:
user> (smart-merge-with vector conj {:a 10 :b 30} {:a 20 :c 30} {:c 1} {:d 100})
;;=> {:a [10 20], :b [30], :c [30 1], :d [100]}
user> (smart-merge-with vector conj {:a [10] :b 30} {:a 20 :c 30} {:c 1} {:d 100})
{:a [[10] 20], :b [30], :c [30 1], :d [100]}
此外,現在你可以更復雜的邏輯添加到地圖融合,例如像一些積累:
user> (smart-merge-with (fn [x] {:items [x] :sum x})
(fn [x y] (-> x
(update :items conj y)
(update :sum + y)))
{:a 10 :b 20} {:b 30 :c 40} {:c 1 :d 2})
;;=> {:a {:items [10], :sum 10},
;; :b {:items [20 30], :sum 50},
;; :c {:items [40 1], :sum 41},
;; :d {:items [2], :sum 2}}
樣子(merge- with(comp flatten vector){:a「b」} {:a「d」} {:a「c」})會這樣做 – zach