2013-05-01 80 views
2

我有一個地圖列表,地圖中的一個鍵是一個可能會重複的鍵。我想重複列表/合併列表。因此,例如:合併與合併:可以簡化嗎?

(def data [{:id 1 :a 2 :b 3 :c 4} {:id 1 :c 5 :d 6} {:id 2 :a 100 :b 101 :c 102} {:id 2 :a 103 :d 104} {:id 2 :a 200 :f 201}]) 

而且我想結束:

[{:id 1 :a 2 :b 3 :c 5 :d 6} {:id 2 :a 200 :b 101 :c 102 :d 104 :f 201}] 

(我措辭的問題,這樣的合併/合併,與作品,但事實是我不真的不在意重疊值會發生什麼,第一個或最後一個可以贏得)。

我得的是:

(vals (apply merge-with merge (into #(hash-map (:id %) %) data))) 

哪些工作,但我不知道是否有一個更好的,更consise,或這樣的優雅,方式。我還想知道性能,因爲我認爲into正在完成序列的完整副本,並將整個內容強制到內存中(原始數據是一個惰性序列)。

+0

對'data'有任何排序保證嗎?我們知道所有具有相同':id'的地圖會一起出現嗎? (如果你不能保證,那麼這是*不可能*做懶惰!) – 2013-05-01 15:12:02

+1

是的,他們將是連續的。它們是數據庫查詢的結果集。 – Kevin 2013-05-01 15:13:12

回答

2

如果您肯定知道,在相同:id地圖將始終是連續的,你可以使用partition-by創建的ID數據的子序列和合並這些子序列:

(map (partial apply merge) (partition-by :id data)) 

這將是懶惰,最後贏了。

+0

太棒了。我還有一個問題:讓我們說一個地圖有重疊的鍵,但有時值是零(我想採取第一個(或最後一個)非零值)?如果這樣做更有意義,我可以單獨提問。 – Kevin 2013-05-01 15:25:30

+0

nm ...'merge-with'可以輕鬆做到這一點。再次感謝! – Kevin 2013-05-01 15:29:54

+0

是的,'merge-with'與合併函數如'%(if(nil?%2)%1%2)''。 – 2013-05-01 15:35:03