Clojure 基于键的地图合并列表

Posted

技术标签:

【中文标题】Clojure 基于键的地图合并列表【英文标题】:Clojure merge list of maps based on keys 【发布时间】:2018-05-09 19:53:39 【问题描述】:

我需要转换以下数据:

[["A" 1] [:ms "A", :s 1, :v 15], ["A" 2] [:ms "A", :s 2, :v 18], ["A" 4] [:ms "A", :s 4, :v 19]
 ["A" 1] [:ms "A", :s 1, :v2 5], ["A" 2] [:ms "A", :s 2, :v2 8], ["B" 4] [:ms "B", :s 4, :v2 9]]

到:

[:ms "A", :s 1, :v 15, :v2 5 :ms "A", :s 2, :v 18, :v2 8 :ms "A", :s 4, :v 19 :ms "B", :s 4, :v2 9]

我正在努力实现,任何帮助将不胜感激:)

【问题讨论】:

我得到了 99% 的答案,然后我意识到你的最后两张地图打破了这种模式。以下是我写的答案:gist.github.com/carcigenicate/d5c766a0407def6ac81cb6775212b12e 请注意最终结果并不完全正确。不知道如何克服这个(太早了:/)。希望有人能给你一个更完整的答案。 这样的东西应该可以工作:(map (partial apply merge) (vals (apply merge-with concat data))) => (:ms "A", :s 1, :v 15, :v2 5 :ms "A", :s 2, :v 18, :v2 8 :ms "A", :s 4, :v 19 :ms "B", :s 4, :v2 9) 【参考方案1】:

这可行:

(def data [["A" 1] [:ms "A", :s 1, :v 15],
            ["A" 2] [:ms "A", :s 2, :v 18],
            ["A" 4] [:ms "A", :s 4, :v 19]
           ["A" 1] [:ms "A", :s 1, :v2 5],
            ["A" 2] [:ms "A", :s 2, :v2 8],
            ["B" 4] [:ms "B", :s 4, :v2 9]])

(map (partial apply merge) (vals (apply merge-with concat data)))

这里是一步一步的解释:

首先我们合并所有顶层映射,连接相等键的值:

(apply merge-with concat data)
;;=> ["A" 1] (:ms "A", :s 1, :v 15 :ms "A", :s 1, :v2 5), 
;;    ["A" 2] (:ms "A", :s 2, :v 18 :ms "A", :s 2, :v2 8), 
;;    ["A" 4] [:ms "A", :s 4, :v 19], 
;;    ["B" 4] [:ms "B", :s 4, :v2 9]

那么对于地图中的每个值,我们应该合并到一个地图:

(apply merge '(:ms "A", :s 1, :v 15 :ms "A", :s 1, :v2 5))
;;=> :ms "A", :s 1, :v 15, :v2 5

所以我们应该使用map:

(map (partial apply merge) (vals (apply merge-with concat data)))
;;=> (:ms "A", :s 1, :v 15, :v2 5
;;    :ms "A", :s 2, :v 18, :v2 8
;;    :ms "A", :s 4, :v 19
;;    :ms "B", :s 4, :v2 9)

【讨论】:

以上是关于Clojure 基于键的地图合并列表的主要内容,如果未能解决你的问题,请参考以下文章

在Clojure中对地图矢量进行排序和排序的更清洁方法?

嵌套地图的Clojure Zipper压制TRIE

markdown 列表交叉合并类似Python中的zip功能(clojure clj ruby​​ scala map vector list)

Clojure按值获取映射键

Clojure 中的可折叠集合是啥?

是否有一个 python 函数可以返回一个添加了新键的新字典,比如 clojure 中的 assoc?