Clojure中的自定义相等区别

Ric*_*fer 11 clojure

在Clojure程序中,我有一个由包含人名和电子邮件的地图组成的数组.

例如

[
    { :name "John" :email "john@gmail.com" }  
    { :name "Batman" :email "batman@gmail.com" }  
    { :name "John Doe" :email "john@gmail.com" }  
 ] 
Run Code Online (Sandbox Code Playgroud)

我想删除重复的条目,为了进行比较,考虑具有相同电子邮件的对等于.在上面的示例中,输出将是:

[
    { :name "John" :email "john@gmail.com" }  
    { :name "Batman" :email "batman@gmail.com" }  
 ] 
Run Code Online (Sandbox Code Playgroud)

在Clojure中实现这一目标的最佳方法是什么?有没有办法让不同的人知道什么等于使用功能?

谢谢.

lee*_*ski 13

还有另一种方法,有点更惯用,我想:

(let [items [{ :name "John" :email "john@gmail.com" }  
             { :name "Batman" :email "batman@gmail.com" }  
             { :name "John Doe" :email "john@gmail.com" }]]
  (map first (vals (group-by :email items))))
Run Code Online (Sandbox Code Playgroud)

输出:

({:name "John", :email "john@gmail.com"} 
 {:name "Batman", :email "batman@gmail.com"})
Run Code Online (Sandbox Code Playgroud)

它是如何工作的:

(group-by :email items) 制作地图,其键是电子邮件,值是使用此电子邮件的记录组

{"john@gmail.com" [{:name "John", :email "john@gmail.com"} 
                   {:name "John Doe", :email "john@gmail.com"}], 
 "batman@gmail.com" [{:name "Batman", :email "batman@gmail.com"}]}
Run Code Online (Sandbox Code Playgroud)

那么你只需要取其vals(记录组)并从中选择第一.

另一种方法是通过电子邮件创建一个排序集,因此它将所有具有相同电子邮件的记录视为相同的记录:

(let [items [{ :name "John" :email "john@gmail.com" }  
             { :name "Batman" :email "batman@gmail.com" }  
             { :name "John Doe" :email "john@gmail.com" }]]
  (into (sorted-set-by #(compare (:email %1) (:email %2))) items))
Run Code Online (Sandbox Code Playgroud)

输出:

#{{:name "Batman", :email "batman@gmail.com"} 
  {:name "John", :email "john@gmail.com"}}
Run Code Online (Sandbox Code Playgroud)

我真的不知道哪一个更具惯用性,而且性能更好.但我打赌第一个.


Hem*_*dhi 7

这样做可以:https://crossclj.info/fun/medley.core/distinct-by.html.

链接中的函数懒洋洋地遍历每个值并存储它看到的所有内容.如果coll已经看到了该值,则不会添加它.

然后你可以把它称为:(distinct-by #(% :email) maps),maps你的人物地图向量在哪里.

  • 由于关键字是函数,更惯用的调用将是"(不同的:电子邮件映射)" (7认同)