我玩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列表的最佳方法是什么?


当前回答

我写了一篇文章,解释了如何扩展Distinct函数,这样你就可以这样做:

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.

这是一篇文章(现在在Web档案中):扩展LINQ -在Distinct函数中指定属性

其他回答

下面的代码在功能上等同于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的回答。

与其他。net版本兼容的最好方法是重写Equals和GetHash来处理这个问题(参见堆栈溢出问题这段代码返回不同的值。然而,我想要的是返回一个强类型集合,而不是匿名类型),但是如果您需要在整个代码中使用通用的东西,那么本文中的解决方案非常好。

从。net 6开始,在Linq中使用新的DistinctBy()扩展有了新的解决方案,所以我们可以做:

var distinctPersonsById = personList.DistinctBy(x => x.Id);

DistinctBy方法的签名:

// Returns distinct elements from a sequence according to a specified
// key selector function.
public static IEnumerable<TSource> DistinctBy<TSource, TKey> (
    this IEnumerable<TSource> source,
    Func<TSource, TKey> keySelector);

我写了一篇文章,解释了如何扩展Distinct函数,这样你就可以这样做:

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.

这是一篇文章(现在在Web档案中):扩展LINQ -在Distinct函数中指定属性

你可以这样做(虽然不是闪电般快):

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

也就是说,“选择列表中没有其他具有相同ID的人的所有人。”

注意,在你的例子中,这只会选择第3个人。我不知道怎么分辨你想要的是哪一个。