C#中的List<T>.Distinct() - 多个条件的EqualityComparer?

5

我有一个对象集合,每个对象都有几个属性。我经常需要获取该集合中多个属性的不同值列表。如果我在该类型上实现了IEqualityComparer,则会为我提供一种单一的标准来获取集合中不同的对象。那么,如何使我能够在此集合上使用多个条件调用Distinct方法?

例如,

  class Product {
    string name ;
    string code ;
    string supplier ;
//etc 
}

想象一下一个这样的产品对象列表。 有时,我想获取列表中不同名称的列表,而在其他时间,则是不同供应商的列表等等。 如果我在这些产品的列表上调用Distinct,基于实现的IEqualityComparer方式,它将始终使用相同的标准,这并不能满足我的目的。
3个回答

14

对于不同调用Distinct的情况,只需提供不同的IEqualityComparer实现即可。请注意IEquatableIEqualityComparer之间的区别 - 通常一个类型不应该为它自己实现IEqualityComparer(因此,Product不会实现IEqualityComparer<Product>)。您可以有不同的实现,比如ProductNameComparer、ProductCodeComparer等。

然而,另一种选择是使用DistinctByMoreLINQ中。

var distinctProducts = products.DistinctBy(p => p.name);

本来会选择Hans的回答作为最佳答案,但他比其他人早了2分钟回复。 - Bhaskar

6
您可以使用接受IEqualityComparer参数的Distinct()重载函数。该函数与MSDN文档中描述的相同。

3
您可以创建一个比较器,它接受Equals和GetHashCode方法的函数参数。类似于:
class Foo
{
    public string Name { get; set; }
    public int Id { get; set; }
}    

class FooComparer : IEqualityComparer<Foo>
{
    public FooComparer(Func<Foo, Foo, bool> equalityComparer, Func<Foo, int> getHashCode)
    {
        EqualityComparer = equalityComparer;
        HashCodeGenerator = getHashCode;
    }

    Func<Foo, Foo, bool> EqualityComparer;
    Func<Foo, int> HashCodeGenerator;

    public bool Equals(Foo x, Foo y)
    {
        return EqualityComparer(x, y);
    }

    public int GetHashCode(Foo obj)
    {
        return HashCodeGenerator(obj);
    }
}

...

List<Foo> foos = new List<Foo>() { new Foo() { Name = "A", Id = 4 }, new Foo() { Name = "B", Id = 4 } };
var list1 = foos.Distinct(new FooComparer((x, y) => x.Id == y.Id, f => f.Id.GetHashCode()));

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