向我提供了一份清单地图:
({: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"]}) 发布于 2018-04-30 14:53:17
不要使用merge,而是使用merge-with,即
(->> 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"]})发布于 2018-04-30 21:29:41
实际上,您并不想对任何东西进行排序或分区:这只是CPU花费在什么东西上的时间,最后您有一个尴尬的数据结构(一个映射列表),而不是一个由“重要”:a值键决定的更方便的映射。
相反,我会将其写成一个约简,其中每一步都在最终映射的适当小节中使用merge-with:
(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轻松查找地图很有帮助,或者如果您希望将结果作为列表返回,您可以轻松地展开它。
https://stackoverflow.com/questions/50102975
复制相似问题