2015-10-07 47 views
7

在Clojure程序中,我有一個由包含人名和電子郵件地圖組成的數組。Clojure中的自定義平等不同

例如

[ 
    { :name "John" :email "[email protected]" } 
    { :name "Batman" :email "[email protected]" } 
    { :name "John Doe" :email "[email protected]" } 
] 

爲了便於比較,我想刪除重複的條目,將具有相同電子郵件的對等於。在上面的例子中,輸出將是:

[ 
    { :name "John" :email "[email protected]" } 
    { :name "Batman" :email "[email protected]" } 
] 

在Clojure中實現此目的的最佳方法是什麼?有沒有一種方法讓不同的人知道什麼等於使用功能?

謝謝。

回答

6

這樣做:https://crossclj.info/fun/medley.core/distinct-by.html

鏈接中的功能懶惰地貫穿每個值,並存儲它所看到的所有內容。如果已經看到coll中的值,則不會添加它。

然後,您可以將其稱爲:(distinct-by #(% :email) maps),其中maps是您的人物地圖矢量。

+6

中使用的示例性情況下由於關鍵字是功能,更慣用調用將'(不同-由:電子郵件地圖)' – Alex

9

另一種方式做到這一點,還挺更地道,我猜:

(let [items [{ :name "John" :email "[email protected]" } 
      { :name "Batman" :email "[email protected]" } 
      { :name "John Doe" :email "[email protected]" }]] 
    (map first (vals (group-by :email items)))) 

輸出:

({:name "John", :email "[email protected]"} 
{:name "Batman", :email "[email protected]"}) 

是如何工作的:

(group-by :email items)使得地圖,其鍵是電子郵件,值是使用此電子郵件的記錄組

{"[email protected]" [{:name "John", :email "[email protected]"} 
        {:name "John Doe", :email "[email protected]"}], 
"[email protected]" [{:name "Batman", :email "[email protected]"}]} 

那麼你只需要取其val(記錄組)並從中選擇第一個。

而另一種方式是創建通過電子郵件有序集合,因此它將對待所有平等的電子郵件記錄作爲平等的記錄:

(let [items [{ :name "John" :email "[email protected]" } 
      { :name "Batman" :email "[email protected]" } 
      { :name "John Doe" :email "[email protected]" }]] 
    (into (sorted-set-by #(compare (:email %1) (:email %2))) items)) 

輸出:

#{{:name "Batman", :email "[email protected]"} 
    {:name "John", :email "[email protected]"}} 

不要」我真的不知道他們哪一個更習慣並且有更好的表現。但我敢打賭第一個。

0

distinct-by可以很容易地被實現爲

(defn distinct-by [f coll] 
    (let [groups (group-by f coll)] 
    (map #(first (groups %)) (distinct (map f coll))))) 

對於此可以像

(distinct-by :email 
      [{:name "John" :email "[email protected]"} 
       {:name "Batman" :email "[email protected]"} 
       {:name "John Doe" :email "[email protected]"}])