Merging maps without overriding keys

徘徊边缘 提交于 2020-01-03 17:37:00

问题


I have a clojure function that returns a sequence of 1-key maps. I want to merge these maps into one map; however, if there are maps with the same key, I don't want to overwrite the values, only to combine them into a vector. merge seems to overwrite, and merge-with seems to seriously distort the type.

I have:

({:foo "hello"}
 {:bar "world"} 
 {:baz "!!!"}
 {:ball {:a "abc", :b "123"}}
 {:ball {:a "def", :b "456"}}
 {:ball {:a "ghi", :b "789"}})

I'd like:

{:foo "hello"
 :bar "world"
 :baz "!!!"
 :ball [{:a "abc", :b "123"} {:a "def", :b "456"} {:a "ghi", :b "789"}]}

Thanks.


回答1:


(def data ...) ;; your list of maps

(apply merge-with (comp flatten vector) data)
;; => {:baz "!!!", :ball ({:b "123", :a "abc"} {:b "456", :a "def"} {:b "789", :a "ghi"}), :bar "world", :foo "hello"}

Note: the use of flatten works in OP's case but is NOT a general way to merge maps while creating vectors of values belonging to colliding keys.




回答2:


The "vector-safe" variant I could come up with has to iterate over all key-value-pairs twice:

(->> (for [[k vs] (group-by key (apply concat data))]
       (if (next vs)
         [k (mapv val vs)]
         (first vs)))
     (into {}))
;; => {:foo "hello",
;;     :bar "world",
;;     :baz "!!!",
;;     :ball [{:a "abc", :b "123"} ...]}

Basically, this groups all values by key and only removes the seq around them if it contains exactly one element.


The fully threaded version (for readability):

(->> (apply concat data)
     (group-by key)
     (map
       (fn [[k vs]]
         (if (next vs)
           [k (mapv val vs)]
           (first vs))))
     (into {}))



回答3:


Having a predictable type for each key would save you headaches when you want to read it back later, but if you have no other choice: merge-with with a custom function would solve it:

(apply merge-with (fn [v1 v2] ((if (vector? v1) conj vector) v1 v2)) data)


来源:https://stackoverflow.com/questions/26639048/merging-maps-without-overriding-keys

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!