Linq Distinct基于对象的属性

时间:2010-01-17 20:48:07

标签: linq distinct

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

喜欢:Distinct(x => x.id)

对我来说没有用的是:.Select(x => x.id).Distinct()因为那样我会找回List<int>而不是List<MyClass>

4 个答案:

答案 0 :(得分:6)

这对我来说听起来像是一个分组构造,因为你需要决定你真正想要返回哪个相同的对象

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

仅因为Id在多个项目中相同并不意味着这些项目在其他属性上是相同的,因此您需要明确决定返回哪个项目。

答案 1 :(得分: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 :(得分:2)

你需要DistinctBy。它不是标准.NET库的一部分,但Jon Skeet为Linq实现了对象here。它也包含在morelinq中。

答案 3 :(得分: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会更清洁。