我正在玩 LINQ 来了解它,但是当我没有一个简单的列表时,我无法弄清楚如何使用 Distinct(一个简单的整数列表很容易做到,这不是问题)。我想在对象的一个或多个属性上使用对象列表中的区别 ?
示例:如果对象是Person
,则具有 Property Id
。如何获取所有 Person 并使用对象的属性Id
对它们使用Distinct
?
Person1: Id=1, Name="Test1"
Person2: Id=1, Name="Test1"
Person3: Id=2, Name="Test2"
我怎样才能得到 Person1 和 Person3?那可能吗?
如果 LINQ 不可能,那么根据. NET 3.5 中的某些属性获得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();
编辑 :这是MoreLINQ 的一部分。
你需要的是一个有效的 “明显的”。我不相信它是 LINQ 的一部分,尽管写起来相当容易:
public static IEnumerable<TSource> DistinctBy<TSource, TKey>
(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
HashSet<TKey> seenKeys = new HashSet<TKey>();
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
构造函数。
如果您希望它看起来像 LINQ 一样,您也可以使用查询语法:
var uniquePeople = from p in people
group p by new {p.ID} //or group by new {p.ID, p.Name, p.Whatever}
into mygroup
select mygroup.FirstOrDefault();