简短问题:
在LINQ to 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
对象列表。
由于Web服务的工作方式[sic],我有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
的具体实现?
我本以为会有一种简单的方法来从基于键的集合中获取“不同”对象。
9条答案
按热度按时间68de4m5k1#
(这里有两个解决方案-第二个见结尾):
我的MiscUtil库有一个
ProjectionEqualityComparer
类(以及两个支持类来使用类型推断)。下面是一个使用它的例子:
下面是代码(注解已删除)
第二种解决方案
要仅针对Distinct执行此操作,可以在MoreLINQ中使用
DistinctBy
扩展:在这两种情况下,
ThrowIfNull
看起来像这样:3j86kqsm2#
基于Charlie Flowers的答案,你可以创建自己的扩展方法来做你想做的事情,在内部使用分组:
你也可以创建一个从EqualityComparer派生的泛型类,但听起来你想避免这样做:
sshcrbum3#
这是我能想到的最好的方法来解决这个问题。不过我还是很好奇是否有一种很好的方法来动态地创建一个
EqualityComparer
。创建查找表并从每个查找表中取“top”
注意:这和@charlie建议的一样,但是使用了ILookup --我认为这是一个群组必须具备的功能。
juud5qan4#
那么一个废弃的
IEqualityComparer
泛型类呢?所以现在你可以使用
Distinct
和一个自定义比较器。您可能可以使用
<GalleryImage>
,但我不确定编译器是否可以推断出类型(现在无法访问它)。并且在附加的扩展方法中:
2g32fytz5#
你可以按键值进行分组,然后从每个组中选择最上面的一项。这对你有用吗?
n53p2ov06#
here正在讨论这个想法,虽然我希望.NET Core团队采用一种从lambda生成
IEqualityComparer<T>
的方法,但我建议您对这个想法进行投票和评论,并使用以下内容:使用方法:
验证码:
z9smfwbn7#
这里有一篇有趣的文章,它扩展了LINQ以达到这个目的...
默认的Distinct根据对象的hashcode比较对象-为了轻松地使您的对象与Distinct一起工作,您可以覆盖GetHashcode方法..但您提到您正在从Web服务中检索对象,因此在这种情况下您可能无法做到这一点。
u59ebvdq8#
这是currently in .NET 8 preview 2。OP将使用
代替他们建议的
更多信息:
https://github.com/dotnet/runtime/pull/75212
ryevplcw9#
在GalleryImage上实现IEquatable,因为它是生成的
另一种方法是将GalleryImage生成为分部类,然后使用另一个具有继承和IEquatable、Equals、GetHash实现的文件。