2015-09-08 59 views
4

所以我有類似下面的列表:如何在clojure中檢查地圖中的重複項?

({:name "yellowtail", :quantity 2} {:name "tuna", :quantity 1} 
{:name "albacore", :quantity 1} {:quantity 1, :name "tuna"}) 

我的目標是搜索地圖項目列表,找到重複鍵,如果有重複,然後遞增量。所以在列表中我有兩個金槍魚映射元素顯示出來。我想刪除一個,只增加另一個的數量。所以結果應該是:

({:name "yellowtail", :quantity 2} {:name "tuna", :quantity 2} 
{:name "albacore", :quantity 1}) 

用:遞增到2金槍魚我試圖使用復發做到這一點沒有成功的數量,我不知道如果RECUR是一個很好的方向與運行。有人能指出我正確的方向嗎?

回答

5

您可以group-by:name你的元素,然後通過map分組集合求和值。

像這樣的事情

(->> your-list 
    (group-by :name) 
    (map (fn [[k v]] 
     {:name k :quantity (apply + (map :quantity v))}))) 

附:我假設你需要總結元素的數量,因爲不清楚你到底需要增加什麼。

2

這是map和reduce的標準用例。

(->> data 
    (map (juxt :name :quantity identity)) 
    (reduce (fn [m [key qty _]] 
       (update m key (fnil (partial + qty) 0))) 
      {}) 
    (map #(hash-map :name (key %1) :quantity (val %1)))) 

我使用identity到的情況下,返回元素要使用其他屬性在地圖上確定唯一性。如果地圖僅包含兩個字段,那麼你可以把它簡化到

(->> data 
    (mapcat #(repeat (:quantity %1) (:name %1))) 
    (frequencies) 
    (map #(hash-map :name (key %1) :quantity (val %1)))) 
0

爲什麼不只是從名稱數量的地圖。取而代之的

({:name "yellowtail", :quantity 2} {:name "tuna", :quantity 1} 
{:name "albacore", :quantity 1} {:quantity 1, :name "tuna"}) 

...我們有

{"yellowtail" 2, "tuna" 1, "albacore" 1} 

我們正在使用的地圖來表示multiset。幾個clojure實現可用,但我沒有使用它們。