在Clojure中,我想将几个映射组合成一个映射,其中具有相同键的映射被组合到一个列表中.
例如:
{:humor :happy} {:humor :sad} {:humor :happy} {:weather :sunny}
Run Code Online (Sandbox Code Playgroud)
应该导致:
{:weather :sunny, :humor (:happy :sad :happy)}
Run Code Online (Sandbox Code Playgroud)
我想过:
(merge-with (comp flatten list) data)
Run Code Online (Sandbox Code Playgroud)
但它效率不高,因为flatten具有O(n)复杂度.
然后我提出:
(defn agg[x y] (if (coll? x) (cons y x) (list y x)))
(merge-with agg data)
Run Code Online (Sandbox Code Playgroud)
但这感觉不是惯用的.还有其他想法吗?
ama*_*loy 12
一种方法是
(defn merge-lists [& maps]
(reduce (fn [m1 m2]
(reduce (fn [m [k v]]
(update-in m [k] (fnil conj []) v))
m1, m2))
{}
maps))
Run Code Online (Sandbox Code Playgroud)
这有点难看,但这只是因为你的价值不是列表.它还强制所有内容都成为一个列表(所以你得到的:weather [:sunny]
不是:weather :sunny
).坦率地说,无论如何,这对你来说可能要容易百万倍.
如果你已经将每个值都作为向量,那么你可以做到(apply merge-with into maps)
.