CSharp - Linq Distinct特定属性

  显示原文与译文双语对照的内容

我正在使用Linq来学习它,但我不知道如何在没有简单的List ( 简单的整数 List 非常简单,这不是问题) 时使用 Distinct 。 如果要在对象的一个或者多个属性上的对象的List 上使用 Distinct?

示例:如果一个对象是"人员",则带有属性"标识"。 如何让所有人使用对象的属性"标识"在它们上使用 Distinct?


Person1: Id=1, Name="Test1"
Person2: Id=1, Name="Test1"
Person3: Id=2, Name="Test2"

如何获得Person1和 Person3? 有可能吗?

在. NET 用Linq来表达,如果不遵守会是最好的方式,建立起一个什么"人员"List,这取决于它的一些属性?

时间:

编辑:这是 MoreLINQ的一部分。

你需要的是一个有效的"distinct-by"。 我不认为它是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 构造函数。

如果要在对象的一个或者多个属性上区分对象的List,则返回?

简单你想要组合它们并从组中选出一个胜出者。


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();

如果你希望它看起来像所有 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();

怎么办:


List<Person> pList = new List<Person>();
/* fill list */

var result = pList.Where(p => p.Name!= null).GroupBy(p => p.Id).Select(grp => grp.First());

帮助你筛选条目( 可能比较复杂) 和 groupby,并选择执行distinct函数。 希望这个有帮助

下面的代码在功能上与乔恩回答上面抛靶的双向飞碟。

在. NET 4.5上测试,应该能在任何早期版本的LINQ上工作。


public static IEnumerable<TSource> DistinctBy2<TSource, TKey>(
 this IEnumerable<TSource> source, Func<TSource, TKey> keySelector)
{
 HashSet<TKey> seenKeys = new HashSet<TKey>();
 return source.Where(element => seenKeys.Add(keySelector(element)));
}

在 Google Code, Incidentially,抛靶听一下乔恩最新的双向飞碟的版本。

我知道这有点晚了。 但是我有写过一篇文章,它讲解了如何扩展的不同功能,以便你可以执行如下操作:


var people = new List<Person>();

people.Add(new Person(1,"a","b"));
people.Add(new Person(2,"c","d"));
people.Add(new Person(1,"a","b"));

foreach (var person in people.Distinct(p => p.ID))
//do stuff with unique list here.

本文:扩展 LINQ - 在Distinct函数中指定一个属性

我需要在多个属性上使用不同的方法你可以查看我的PowerfulExtensions 库。 目前它处于一个非常年轻的阶段,但是你已经可以使用不同的方法,比如 Distinct,Union,Intersect,除了任何数量的属性;

这就是你使用它的方式:


using PowerfulExtensions.Linq;
...
var distinct = myArray.Distinct(x => x.A, x => x.B);

你可以这样做:


people.Where(p =>!people.Any(q => (p!= q && p.Id == q.Id)));

也就是说,"选择 List 中没有其他人的所有人具有相同的标识。"

注意,在你的示例中,只选择 person 3 。 我不确定如何判断你想要的,前两个。

...