通过列表中的两个属性选择distinct

时间:2012-08-04 18:37:11

标签: c# list distinct linq-to-objects

我的list<message>包含GuidDateTime类型的属性(以及其他属性)。我想摆脱该列表中GuidDateTime相同(除了一个)的所有项目。有时候这两个属性与列表中的其他项目相同,但其他属性会有所不同,所以我不能只使用.Distinct()

List<Message> messages = GetList();
//The list now contains many objects, it is ordered by the DateTime property

messages = from p in messages.Distinct(  what goes here? ); 

这就是我现在所拥有的,但似乎应该有更好的方式

List<Message> messages = GetList();

for(int i = 0; i < messages.Count() - 1)  //use Messages.Count() -1 because the last one has nothing after it to compare to
{
    if(messages[i].id == messages[i+1}.id && messages[i].date == message[i+1].date)
    {
        messages.RemoveAt(i+1);
    {
    else
    {
         i++
    }
}

5 个答案:

答案 0 :(得分:62)

LINQ to Objects不能以内置方式轻松提供此功能,但MoreLINQ有一个方便的DistinctBy方法:

messages = messages.DistinctBy(m => new { m.id, m.date }).ToList();

答案 1 :(得分:15)

Jon Skeet的DistinctBy肯定是要走的路,但是如果你有兴趣定义自己的扩展方法,你可能会想到这个更简洁的版本:

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

具有相同的签名:

messages = messages.DistinctBy(x => new { x.id, x.date }).ToList();

答案 2 :(得分:2)

这个怎么样?

var messages = messages
               .GroupBy(m => m.id)
               .GroupBy(m => m.date)
               .Select(m => m.First());

答案 3 :(得分:1)

您可以查看我的PowerfulExtensions图书馆。目前它处于一个非常年轻的阶段,但你已经可以使用Distinct,Union,Intersect等方法,除了任何数量的属性;

这是您使用它的方式:

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

答案 4 :(得分:1)

尝试一下

 var messages = (from g1 in messages.GroupBy(s => s.id) from g2 in g1.GroupBy(s => s.date) select g2.First()).ToList();