在clojure,如何合并几个映射组合与相同的键到列表中的映射? [英] In clojure, how to merge several maps combining mappings with same key into a list?

查看:128
本文介绍了在clojure,如何合并几个映射组合与相同的键到列表中的映射?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆