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 基于键的地图合并列表的主要内容,如果未能解决你的问题,请参考以下文章
markdown 列表交叉合并类似Python中的zip功能(clojure clj ruby scala map vector list)