如何在clojure中合并地图列表

如何在clojure中合并地图列表,clojure,Clojure,我得到了一份地图清单: ({:a 1 :b ["red" "blue"]} {:a 2 :b ["green"]} {:a 1 :b ["yellow"]} {:a 2 :b ["orange"]}) 我需要将它们结合起来,最终看起来像这样: ({:a 1 :b ["red" "blue" "yellow"]} {:a 2 :b ["green" "orange"]}) 其中,根据键“a”的值组合贴图。 到目前为止,我有这个 (->> (sort-by :a) (par

我得到了一份地图清单:

({:a 1 :b ["red" "blue"]} {:a 2 :b ["green"]} {:a 1 :b ["yellow"]} {:a 2 :b ["orange"]})
我需要将它们结合起来,最终看起来像这样:

({:a 1 :b ["red" "blue" "yellow"]} {:a 2 :b ["green" "orange"]})
其中,根据键“a”的值组合贴图。 到目前为止,我有这个

(->> (sort-by :a)
     (partition-by :a)
     (map (partial apply merge)))
但是合并将覆盖“b”中的向量,最后一个给我

({:a 1 :b ["yellow"]} {:a 2 :b ["orange"]}) 

使用
合并
,而不是
合并
,即

(->> a (sort-by :a) 
       (partition-by :a) 
       (map (partial 
          apply 
          merge-with (fn [x y] (if (= x y) x (into x y))))))
输出

({:a 1, :b ["red" "blue" "yellow"]} {:a 2, :b ["green" "orange"]})

你并不想对任何东西进行排序或分区:这只是CPU时间的浪费,最终你会得到一个笨拙的数据结构(地图列表),而不是更方便的东西,一个由“重要的”
:a
值键入的地图

相反,我将把它写成reduce,其中每一步都在最终映射的相应小节上使用
合并

(defn combine-by [k ms]
  (reduce (fn [acc m]
            (update acc (get m k) 
                    (partial merge-with into) 
                    (dissoc m k)))
          {}, ms))
之后我们有

user=> (combine-by :a '({:a 1 :b ["red" "blue"]} 
                        {:a 2 :b ["green"]} 
                        {:a 1 :b ["yellow"]} 
                        {:a 2 :b ["orange"]}))
{1 {:b ["red" "blue" "yellow"]}, 2 {:b ["green" "orange"]}}
这是一个很有用的键,可以通过特定的
:a
轻松查找地图,或者如果您希望将结果作为列表返回,则可以轻松展开它