我玩LINQ来了解它,但我不知道如何使用鲜明当我没有一个简单的列表(一个简单的整数列表是很容易做到的,这不是问题)。如果我想使用鲜明的列表<TElement>上的一个或多个属性的TElement?
示例:如果一个对象是Person,具有属性Id。我怎么能得到所有人,并使用鲜明对他们与对象的属性Id ?
Person1: Id=1, Name="Test1"
Person2: Id=1, Name="Test1"
Person3: Id=2, Name="Test2"
如何得到Person1和Person3?这可能吗?
如果用LINQ是不可能的,那么根据Person的某些属性获得Person列表的最佳方法是什么?
如果我想根据一个或多个属性获得一个不同的列表,该怎么办?
简单!你想把他们分组,然后从中选出一个优胜者。
List<Person> distinctPeople = allPeople
.GroupBy(p => p.PersonId)
.Select(g => g.First())
.ToList();
如果你想在多个属性上定义组,如下所示:
List<Person> distinctPeople = 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
如果你使用的是旧的。net版本,扩展方法不是内置的,那么你可以定义你自己的扩展方法:
public static class EnumerableExtensions
{
public static IEnumerable<T> DistinctBy<T, TKey>(this IEnumerable<T> enumerable, Func<T, TKey> keySelector)
{
return enumerable.GroupBy(keySelector).Select(grp => grp.First());
}
}
用法示例:
var personsDist = persons.DistinctBy(item => item.Name);
下面的代码在功能上等同于Jon Skeet的答案。
在. net 4.5上测试,应该可以在任何早期版本的LINQ上运行。
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
HashSet<TKey> seenKeys = new HashSet<TKey>();
return source.Where(element => seenKeys.Add(keySelector(element)));
}
顺便说一句,请在谷歌Code上查看Jon Skeet的最新版本的DistinctBy.cs。
更新2022-04-03
根据Andrew McClement的评论,最好接受John Skeet的回答。