LINQ中针对特定属性的Distinct()函数
LINQ中针对特定属性的Distinct()函数
我正在使用LINQ进行学习,但是我无法弄清楚如何在没有简单列表的情况下使用Distinct
(简单整数列表很容易做到,这不是问题)。 如果我想在一个或多个属性上使用TElement
的List
上的Distinct
,该怎么办?
例如:如果一个对象是Person
,具有属性Id
。 我如何获取所有Person
并使用对象的属性Id
对它们进行Distinct
?
Person1: Id=1, Name="Test1" Person2: Id=1, Name="Test1" Person3: Id=2, Name="Test2"
我怎么能仅获取Person1
和Person3
? 是否有可能?
如果使用LINQ不可能,那么根据其某些属性拥有Person
列表的最佳方法是什么?
admin 更改状态以发布 2023年5月25日
EDIT: 这现在是MoreLINQ的一部分。
你需要的是有效的“通过不同”功能。我不认为它已经成为LINQ的一部分,尽管很容易编写:
public static IEnumerableDistinctBy (this IEnumerable source, Func keySelector) { HashSet seenKeys = new HashSet (); foreach (TSource element in source) { if (seenKeys.Add(keySelector(element))) { yield return element; } } }
所以,为了仅使用Id
属性查找不同的值,您可以使用:
var query = people.DistinctBy(p => p.Id);
要使用多个属性,您可以使用匿名类型,它适当地实现了相等性:
var query = people.DistinctBy(p => new { p.Id, p.Name });
未经测试,但应该可以工作(现在至少可以编译)。
它假定键的默认比较器,如果您想传递相等比较器,只需将其传递给HashSet
构造函数即可。
如果我想基于一个或多个属性获得不同的列表,该怎么办?
简单!你想要把它们分组并从组中挑选一个获胜者。
ListdistinctPeople = allPeople .GroupBy(p => p.PersonId) .Select(g => g.First()) .ToList();
如果您想在多个属性上定义组,请按如下方式操作:
ListdistinctPeople = allPeople .GroupBy(p => new {p.PersonId, p.FavoriteColor} ) .Select(g => g.First()) .ToList();
注意:某些查询提供程序无法解决每个组必须至少有一个元素,并且 First 是在那种情况下调用的适当方法。如果您发现自己在使用这样的查询提供程序,请尝试使用 FirstOrDefault 帮助您顺利进行查询。
注2:考虑使用此答案来获得与 EF Core (EF Core 6 之前) 兼容的方法。 https://stackoverflow.com/a/66529949/8155