是的,所以我有一个可枚举的,并希望从中获得不同的值 .
使用 System.Linq
,当然有一个名为 Distinct
的扩展方法 . 在简单的情况下,它可以在没有参数的情况下使用,例如:
var distinctValues = myStringList.Distinct();
好的,但是如果我有一个可以指定相等性的可枚举对象,那么唯一可用的重载是:
var distinctValues = myCustomerList.Distinct(someEqualityComparer);
equality comparer参数必须是 IEqualityComparer<T>
的实例 . 当然,我可以做到这一点,但它有点冗长,而且很好 .
我所期望的是一个需要lambda的重载,比如Func <T,T,bool>:
var distinctValues
= myCustomerList.Distinct((c1, c2) => c1.CustomerId == c2.CustomerId);
有人知道是否存在某些此类扩展或某些等效的解决方法?或者我错过了什么?
或者,是否有一种方法可以指定IEqualityComparer内联(embarass me)?
Update
我在一个关于这个主题的MSDN论坛上找到了Anders Hejlsberg给post的回复 . 他说:
您将要遇到的问题是,当两个对象比较相等时,它们必须具有相同的GetHashCode返回值(否则Distinct内部使用的哈希表将无法正常运行) . 我们使用IEqualityComparer,因为它将Equals和GetHashCode的兼容实现打包到一个接口中 .
我认为那是有道理的..
18 回答
没有这样的扩展方法重载 . 我在过去发现这令人沮丧,因此我经常写一个助手类来处理这个问题 . 目标是将
Func<T,T,bool>
转换为IEqualityComparer<T,T>
.例
这允许您编写以下内容
IEnumerable
lambda扩展名:用法:
Microsoft System.Interactive package有一个Distinct版本,它带有一个键选择器lambda . 这实际上与Jon Skeet的解决方案相同,但它可能有助于人们了解并查看库的其余部分 .
To Wrap things up . 我想像我这样来到这里的大多数人都希望 simplest 解决方案尽可能 without using any libraries 并尽可能 performance .
(对我而言,接受的方法对我而言,我认为在表现方面是一种矫枉过正 . )
这是一个使用 IEqualityComparer 接口的简单扩展方法,该接口也适用于空值 .
Usage:
Extension Method Code
如果
Distinct()
不会产生唯一结果,请尝试以下方法:我在这里看到的所有解决方案都依赖于选择已经相当的领域 . 但是,如果需要以不同的方式进行比较,this solution here似乎通常会起作用,例如:
它看起来像你想DistinctBy来自MoreLINQ . 然后你可以写:
这是
DistinctBy
的简化版本(没有无效检查,也没有指定自己的密钥比较器的选项):以下是您可以这样做的方法:
此方法允许您通过指定一个参数(如
.MyDistinct(d => d.Name)
)来使用它,但它也允许您将条件指定为第二个参数,如下所示:N.B. 这也允许您指定其他功能,例如
.LastOrDefault(...)
.如果你想公开这个条件,你可以通过实现它来使它变得更简单:
在这种情况下,查询将如下所示:
N.B. 这里,表达式更简单,但注意
.MyDistinct2
隐式使用.FirstOrDefault(...)
.Note: 以上示例使用以下演示类
速记解决方案
你可以使用 InlineComparer
Usage sample :
资料来源:https://stackoverflow.com/a/5969691/206730
Using IEqualityComparer for Union
Can I specify my explicit type comparator inline?
我假设您有一个IEnumerable,并且在您的示例委托中,您希望c1和c2引用此列表中的两个元素?
我相信你可以通过自我连接var distinctResults =来自我的列表中的myList join c2中的c1来实现这一点
您可以使用LambdaEqualityComparer:
换个角度说:
序列返回不同的元素通过属性'_myCaustomerProperty'来比较它们 .
这是一个简单的扩展方法,可以满足我的需求......
遗憾的是,他们没有将这样一个独特的方法烘焙到框架中,但是嘿嘿 .
这将做你想要的,但我不知道性能:
至少它不是冗长的 .
一个棘手的方法是使用
Aggregate()
扩展,使用字典作为累加器,将键属性值作为键:GroupBy风格的解决方案正在使用
ToLookup()
:我用过的东西对我来说效果很好 .