完全外连接在Clojure中的两个地图序列 [英] Full outer join two sequences of maps in Clojure
本文介绍了完全外连接在Clojure中的两个地图序列的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
给定:
(def seq1 ({:id 1 :val 10} {:id 2 :val 20}))
(def seq2 ({:id 1 :val 12} {:id 3 :val 30}))
b $ b
在每个序列中,:id
值保证在该序列中是唯一的,但不一定是有序的。
Within each sequence, the :id
value is guaranteed to be unique in that sequence, though not necessarily ordered.
如何通过:id
键连接这两个映射序列,以便结果如下所示?
How can these two sequences of maps be joined by the :id
key, so that the result is as shown?
{1 [{:id 1 :val 10} {:id 1 :val 12}],
2 [{:id 2 :val 20} nil ],
3 [nil {:id 3 :val 30}]}
最终的结果是一个对的地图。这类似于一个完整的外连接,其中不仅交集,而且两个集合的差异也包含在输出中。
The ultimate result is a map of pairs. This is similar to a full outer join, where not only the intersection, but also the difference of the two sets is included in the output.
推荐答案
这里是我想出的答案,但我确信它可以更优雅或潜在的更好的性能。
Here's the answer I came up with, however I'm sure it can be made more elegant or potentially to have better performance.
(defn seq-to-map [seq key]
(into {} (map (fn [{id key :as m}] [id m]) seq)))
(defn outer-join-maps [seq1 seq2 key]
(let [map1 (seq-to-map seq1 key)
map2 (seq-to-map seq2 key)
allkeys (set (clojure.set/union (keys map1) (keys map2)))]
(into {} (map (fn [k] [k [(get map1 k) (get map2 k)]]) allkeys))))
以下测试通过:
(fact {:midje/description "Sequence to map"}
(seq-to-map [{:a 1, :b 1} {:a 2, :b 2}] :a)
=> {1 {:a 1, :b 1}, 2 {:a 2, :b 2}}
(seq-to-map [{:a 1, :b 1} {:a 1, :b 2}] :a)
=> {1 {:a 1, :b 2}} ; takes last value when a key is repeated
(seq-to-map [] :a)
=> {})
(fact {:midje/description "Sequence merging"}
(let [seq1 [{:id 1 :val 10} {:id 2 :val 20}]
seq2 [{:id 1 :val 12} {:id 3 :val 30}]]
(outer-join-maps seq1 seq2 :id)
=> {1 [{:id 1 :val 10} {:id 1 :val 12}],
2 [{:id 2 :val 20} nil],
3 [nil {:id 3 :val 30}]}))
这篇关于完全外连接在Clojure中的两个地图序列的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文