我第一次尝试
(merge-with list maps)
它适用于具有单一值的地图, 但对于像
这样的东西{:a [1 2]} {:a [2 3]} {:a [3 4]}
它给了我
{:a (([1 2] [2 3]) [3 4])}
但我想要
{:a ([1 2] [2 3] [3 4])}
我刚刚发现我可以使用vector包装地图的val:
(defn my-merge
[& coll]
(let [maps (map #(assoc % (first (keys %)) [(first (vals %))]) coll)]
(apply merge-with concat maps)))
但是let绑定似乎太嵌套了,有没有更简单的函数可以用来代替concat?所以我可以有一些代码,如:
(merge-with the-function maps)
答案 0 :(得分:0)
你可以试试这个:
(merge-with (fn [a b]
(if (list? a)
(conj a b)
(list a b)))
maps)
;; {:a ([3 4] [1 2] [2 3])}
它可以工作,但依赖于输出集合的类型 - 在这种情况下列表。这是我提出的最短时间。
希望这有帮助。
答案 1 :(得分:0)
版本1
(defn my-merge [f & mlist]
(into {}
(map (fn [[k v]] [k (apply f (map val v))])
(group-by key (apply concat mlist)))))
(my-merge list
{:a [1 2]}
{:a [2 3] :b :two}
{:a [3 4] :b :one})
=> {:a ([1 2] [2 3] [3 4]) :b (:two :one)}
第2版
(defn my-merge [f initv & mlist]
(apply merge-with f
(apply merge-with (fn [_ _] initv) mlist)
mlist))
(my-merge conj ()
{:a [1 2]}
{:a [2 3] :b :two}
{:a [3 4] :b :one})
=> {:b (:one :two), :a ([3 4] [2 3] [1 2])}
答案 2 :(得分:0)
以下解决方案还确保列表中项目的顺序基于地图的顺序。
(def maps [{:a [1 2]}
{:a [2 3] :b :two}
{:a [3 4] :b :one}])
(into {} (for [k (into #{} (mapcat keys maps))
:let [obj (Object.)]]
[k (filter (partial not= obj)
(map #(get % k obj) maps))]))
=> {:a ([1 2] [2 3] [3 4]), :b (:two :one)}