Distinct()如何在对象列表中查找唯一元素

时间:2015-06-16 20:07:16

标签: c# linq distinct

有一个非常简单的课程:

public class LinkInformation
{
    public LinkInformation(string link, string text, string group)
    {
        this.Link = link;
        this.Text = text;
        this.Group = group;
    }

    public string Link { get; set; }
    public string Text { get; set; }
    public string Group { get; set; }

    public override string ToString()
    {
        return Link.PadRight(70) + Text.PadRight(40) + Group;
    }
}

我创建了这个类的对象列表,其中包含多个重复项。

所以,我尝试使用Distinct()获取唯一值列表。

但它不起作用,所以我实施了

IComparable<LinkInformation>

    int IComparable<LinkInformation>.CompareTo(LinkInformation other)
    {
        return this.ToString().CompareTo(other.ToString());
    }

然后......

IEqualityComparer<LinkInformation>

    public bool Equals(LinkInformation x, LinkInformation y)
    {
        return x.ToString().CompareTo(y.ToString()) == 0;
    }

    public int GetHashCode(LinkInformation obj)
    {
        int hash = 17;
        // Suitable nullity checks etc, of course :)
        hash = hash * 23 + obj.Link.GetHashCode();
        hash = hash * 23 + obj.Text.GetHashCode();
        hash = hash * 23 + obj.Group.GetHashCode();
        return hash;
    }

使用Distinct的代码是:

    static void Main(string[] args)
    {
        string[] filePath = {   @"C:\temp\html\1.html",
                                @"C:\temp\html\2.html",
                                @"C:\temp\html\3.html",
                                @"C:\temp\html\4.html",
                                @"C:\temp\html\5.html"};

        int index = 0;

        foreach (var path in filePath)
        {
            var parser = new HtmlParser();

            var list = parser.Parse(path);

            var unique = list.Distinct();

            foreach (var elem in unique)
            {
                var full = new FileInfo(path).Name;
                var file = full.Substring(0, full.Length - 5);
                Console.WriteLine((++index).ToString().PadRight(5) + file.PadRight(20) + elem);
            }
        }

        Console.ReadKey();
    }

要使Distinct()正常工作需要做些什么?

4 个答案:

答案 0 :(得分:5)

当您调用它时,您需要将您已创建的IEqualityComparer实际传递给Disctinct。它有两个重载,一个不接受参数,另一个接受IEqualityComparer。如果您没有提供比较器,则使用默认值,默认比较器不会比较您想要比较的对象。

答案 1 :(得分:1)

如果要从某些自定义数据类型的对象序列中返回不同的元素,则必须在类中实现IEquatable泛型接口。

这是一个示例实现:

public class Product : IEquatable<Product>
{
    public string Name { get; set; }
    public int Code { get; set; }

    public bool Equals(Product other)
    {

        //Check whether the compared object is null.
        if (Object.ReferenceEquals(other, null)) return false;

        //Check whether the compared object references the same data.
        if (Object.ReferenceEquals(this, other)) return true;

        //Check whether the products' properties are equal.
        return Code.Equals(other.Code) && Name.Equals(other.Name);
    }

    // If Equals() returns true for a pair of objects 
    // then GetHashCode() must return the same value for these objects.

    public override int GetHashCode()
    {

        //Get hash code for the Name field if it is not null.
        int hashProductName = Name == null ? 0 : Name.GetHashCode();

        //Get hash code for the Code field.
        int hashProductCode = Code.GetHashCode();

        //Calculate the hash code for the product.
        return hashProductName ^ hashProductCode;
    }
}

这就是你如何做到实际的区别:

Product[] products = { new Product { Name = "apple", Code = 9 }, 
                       new Product { Name = "orange", Code = 4 }, 
                       new Product { Name = "apple", Code = 9 }, 
                       new Product { Name = "lemon", Code = 12 } };

//Exclude duplicates.

IEnumerable<Product> noduplicates =
    products.Distinct();

答案 2 :(得分:1)

如果您对通过单个属性定义“清晰度”感到满意,则可以执行

list
    .GroupBy(x => x.Text)
    .Select(x => x.First())

获取“唯一”项目列表。

无需与IEqualityComparer等人混在一起

答案 3 :(得分:1)

不使用Distinct和比较器,如何:

list.GroupBy(x => x.ToString()).Select(x => x.First())

我知道这个解决方案不是确切问题的答案,但我认为对其他解决方案开放是有效的。