在clojure,如何合并几个映射组合与相同的键到列表中的映射? [英] In clojure, how to merge several maps combining mappings with same key into a list?
问题描述
在Clojure中,我想将几个地图合并为一个地图,将具有相同键值的映射合并成一个列表。
In Clojure, I would like to combine several maps into a single map where mappings with same key are combined into a list.
例如:
{:humor :happy} {:humor :sad} {:humor :happy} {:weather :sunny}
应导致:
{:weather :sunny, :humor (:happy :sad :happy)}
:
(merge-with (comp flatten list) data)
但是效率不高,因为flatten有 O(n)复杂性。
But it is not efficient because flatten has O(n) complexity.
然后我想出了:
(defn agg[x y] (if (coll? x) (cons y x) (list y x)))
(merge-with agg data)
但感觉不到惯用。任何其他想法?
But it feels not idiomatic. Any other idea?
推荐答案
一种方法是
(defn merge-lists [& maps]
(reduce (fn [m1 m2]
(reduce (fn [m [k v]]
(update-in m [k] (fnil conj []) v))
m1, m2))
{}
maps))
这有点丑,但是这只是因为你的值不是已经列出的。它还强制所有为列表(因此您会得到:weather [:sunny]
,而不是:weather :sunny
)。坦率地说,这很可能是你工作的百万分之一。
It's a bit ugly, but that's only because your values aren't already lists. It also forces everything to be a list (so you'd get :weather [:sunny]
rather than :weather :sunny
). Frankly, this is likely to be a million times easier for you to work with anyway.
如果你已经有每个值作为一个向量,你可以简单地做(apply merge-with into maps)
。
If you had each value as a vector already, you could simply do (apply merge-with into maps)
.
这篇关于在clojure,如何合并几个映射组合与相同的键到列表中的映射?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!