Clojure distinct中的习俗平等
在Clojure程序中,我有一个由包含人名和电子邮件的地图组成的数组 e、 g 出于比较的目的,我想删除重复条目,因为具有相同电子邮件的对是相等的。在上述示例中,输出为:Clojure distinct中的习俗平等,clojure,Clojure,在Clojure程序中,我有一个由包含人名和电子邮件的地图组成的数组 e、 g 出于比较的目的,我想删除重复条目,因为具有相同电子邮件的对是相等的。在上述示例中,输出为: [ { :name "John" :email "john@gmail.com" } { :name "Batman" :email "batman@gmail.com" } ] 在Clojure实现这一目标的最佳方式是什么?有没有办法让distinct知道使用什么等于函数 谢谢。这样就可以了:
[
{ :name "John" :email "john@gmail.com" }
{ :name "Batman" :email "batman@gmail.com" }
]
在Clojure实现这一目标的最佳方式是什么?有没有办法让distinct知道使用什么等于函数
谢谢。这样就可以了:
链接中的函数惰性地遍历每个值,并存储所看到的所有内容。如果已经看到coll中的值,则不会添加该值
然后,您可以将其称为:distinct by%:email maps,其中maps是您的人物地图矢量。还有另一种方法,我想更为惯用:
(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))))
输出:
({:name "John", :email "john@gmail.com"}
{:name "Batman", :email "batman@gmail.com"})
#{{:name "Batman", :email "batman@gmail.com"}
{:name "John", :email "john@gmail.com"}}
这就是它的工作原理:
分组依据:电子邮件项生成一个地图,其键是电子邮件,值是此电子邮件的记录组
{"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"}]}
然后,您只需获取其VAL记录组并从中选择第一个
另一种方法是通过电子邮件创建一个排序集,因此它会将具有相同电子邮件的所有记录视为相同的记录:
(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))
输出:
({:name "John", :email "john@gmail.com"}
{:name "Batman", :email "batman@gmail.com"})
#{{:name "Batman", :email "batman@gmail.com"}
{:name "John", :email "john@gmail.com"}}
真的不知道哪一个更地道,性能更好。但是我敢打赌第一个。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 "john@gmail.com"}
{:name "Batman" :email "batman@gmail.com"}
{:name "John Doe" :email "john@gmail.com"}])
由于关键字是函数,因此更惯用的调用方式是:电子邮件映射