基于对象属性的Linq Distinct

8

是否可以基于List中对象的属性获取不同的元素?

类似这样:Distinct(x => x.id)

对我没有用的是以下内容:.Select(x => x.id).Distinct(),因为那样我会得到一个List<int>而不是List<MyClass>


为什么LINQ没有返回满足条件的不同值的方法? - Mark Byers
4个回答

6

这听起来像是一种分组结构,因为你需要决定你想要返回哪个看似相同的对象

var q = from x in foo
        group x by x.Id into g
        select g.First(); // or some other selection from g

虽然多个项的Id相同,但并不意味着这些项在其他属性上也相同,因此您需要明确决定返回哪个项。


5
您可以实现自己的 IEqualityComparer<T> 并将其传递给 Distinct 来完成此操作:
class SomeType {
    public int id { get; set; }
    // other properties
}
class EqualityComparer : IEqualityComparer<SomeType> {
    public bool Equals(SomeType x, SomeType y) {
        return x.id == y.id;
    }

    public int GetHashCode(SomeType obj) {
        return obj.id.GetHashCode();
    }
}

然后:

// elements is IEnumerable<SomeType>
var distinct = elements.Distinct(new EqualityComparer());
// distinct is IEnumerable<SomeType> and contains distinct items from elements
// as per EqualityComparer

2

有一个Enumerable.Distinct()的重载版本,它接受IEqualityComparer

这里是一个例子,我用它来按奇偶数过滤整数:

    class IntParitiyComparer : IEqualityComparer<int>
    {
        public bool Equals(int x, int y)
        {
            return x % 2 == y % 2;
        }

        public int GetHashCode(int obj)
        {
            return obj % 2;
        }
    }

    static void Main(string[] args)
    {
        var x = new int[] { 1, 2, 3, 4 }.Distinct(new IntParitiyComparer());

        foreach (var y in x) Console.WriteLine(y);
    }

这样写有些笨重;使用 DistinctBy 会更加简洁。


2
你需要使用DistinctBy。它不是标准.NET库的一部分,但Jon Skeet为Linq to objects实现了它(这里)。它也包含在morelinq中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接