重要提示:这是 NOT A LINQ-TO-SQL 问题 . 这是对象的LINQ .
Short question:
LINQ中是否有一种简单的方法可以根据对象的键属性从列表中获取不同的对象列表 .
Long question:
我正在尝试在 objects 列表上执行Distinct()操作,该列表具有作为其属性之一的键 .
class GalleryImage {
public int Key { get;set; }
public string Caption { get;set; }
public string Filename { get; set; }
public string[] Tags {g et; set; }
}
我有一个包含 GalleryImage[]
的 Gallery
对象列表 .
由于webservice的工作方式[原文如此],我有 GalleryImage
对象的重复 . 我认为使用 Distinct()
来获得一个独特的列表是一件简单的事情 .
这是我想要使用的LINQ查询:
var allImages = Galleries.SelectMany(x => x.Images);
var distinctImages = allImages.Distinct<GalleryImage>(new
EqualityComparer<GalleryImage>((a, b) => a.id == b.id));
问题是 EqualityComparer
是一个抽象类 .
我不想:
-
在
GalleryImage
上实现IEquatable,因为它是生成的 -
必须编写一个单独的类来实现
IEqualityComparer
作为shown here
EqualityComparer
在某个地方是否有一个我错过的具体实现?
我原本以为会有一种简单的方法可以根据键从一组中获取“不同”的对象 .
8 回答
(这里有两种解决方案 - 见第二种解决方案):
我的MiscUtil库有一个
ProjectionEqualityComparer
类(以及两个支持类来使用类型推断) .以下是使用它的示例:
这是代码(删除了评论)
Second solution
要仅针对Distinct执行此操作,您可以在MoreLINQ中使用DistinctBy扩展名:
在这两种情况下,
ThrowIfNull
看起来像这样:基于Charlie Flowers的回答,您可以创建自己的扩展方法来执行您想要的内部使用分组的方法:
您还可以创建一个派生自EqualityComparer的泛型类,但听起来您想要避免这种情况:
这是我能想出的最好的问题 . 仍然好奇是否有一个很好的方式来创建一个
EqualityComparer
虽然 .创建查找表并从每个表中取“顶部”
注意:这与@charlie建议的相同,但是使用ILookup - 我认为无论如何都是一个组 .
您可以按键值进行分组,然后从每个组中选择顶部项目 . 这对你有用吗?
扔掉
IEqualityComparer
泛型课怎么样?所以现在你可以使用
Distinct
.您可能能够使用
<GalleryImage>
,但我现在可以访问它 . )并在一个额外的扩展方法:
这是一篇有趣的文章,为此目的扩展了LINQ ... http://www.singingeels.com/Articles/Extending_LINQ__Specifying_a_Property_in_the_Distinct_Function.aspx
默认Distinct根据其哈希码对对象进行比较 - 轻松使对象与Distinct一起使用,您可以覆盖GetHashcode方法..但是您提到您正在从Web服务检索对象,因此您可能无法做到这一点在这种情况下 .
另一种方法是将GalleryImage生成为部分类,然后使用继承和IEquatable,Equals,GetHash实现另一个文件 .
这个想法正在争论here,虽然我希望.NET Core团队采用一种方法从lambda生成
IEqualityComparer<T>
,但我建议你对这个想法进行投票和评论,并使用以下内容:用法:
码: