C# 如何使用 IEqualityComparer、LinQ Distinct 从集合中删除重复项

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16983618/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-10 08:17:19  来源:igfitidea点击:

How to remove duplicates from collection using IEqualityComparer, LinQ Distinct

c#linqlist

提问by Gun

I am unable to remove the duplicates from collection , i have implemented IEqualityComparer for the class Employee still i am not getting the output

我无法从集合中删除重复项,我已经为 Employee 类实现了 IEqualityComparer 仍然没有得到输出

static void Main(string[] args)
    {
        List<Employe> Employeecollection = new List<Employe>();

        Employeecollection.Add(new Employe("abc","def"));
        Employeecollection.Add(new Employe("lmn","def"));
        Employeecollection.Add(new Employe("abc", "def"));

        IEnumerable<Employe> coll = Employeecollection.Distinct(new Employe());

        foreach (Employe item in coll)
        {
            Console.WriteLine(item.fName + "   " + item.lName );
        }

    }

The Below is the Employee class implementation , here i implemented IEqualityComparer

下面是Employee类的实现,这里我实现了IEqualityComparer

class Employe : IEqualityComparer<Employe>
{
    public string fName { get; set; }
    public string lName { get; set; }

    public Employe()
    {

    }

    public Employe(string firstName, string LastName)
    {
        this.fName = firstName;
        this.lName = LastName;
    }

    #region IEqualityComparer<pcf> Members

    public bool Equals(Employe x, Employe y)
    {
        if (x.fName == y.fName && x.lName == y.lName)
        {
            return true;
        }

        return false;
    }

    public int GetHashCode(Employe obj)
    {
        return obj.GetHashCode();
    }

    #endregion
}

采纳答案by spender

Forget IEqualityComparer and just use Linq directly:

忘记 IEqualityComparer,直接使用 Linq:

EmployeeCollection.GroupBy(x => new{x.fName, x.lName}).Select(g => g.First());

回答by Ilya Ivanov

You need to override GetHashCodemethod in your Employee. You haven't done this. One example of a good hashing method is given below: (generated By ReSharper)

您需要覆盖GetHashCode员工中的方法。你没有这样做。下面给出了一个好的散列方法的例子:(由ReSharper生成)

public override int GetHashCode()
{
    return ((this.fName != null ? this.fName.GetHashCode() : 0) * 397) ^ (this.lName != null ? this.lName.GetHashCode() : 0);
}

now after Distinctis called, foreach loop prints:

现在Distinct调用后,foreach 循环打印:

abc   def
lmn   def

In your case you are calling object's class GetHashCode, which knows nothing about internal fields.

在您的情况下,您正在调用 object 的 class GetHashCode,它对内部字段一无所知。

One simple note, MoreLINQcontains DistinctByextension method, which allows you to do:

一个简单的说明,MoreLINQ包含DistinctBy扩展方法,它允许您执行以下操作:

IEnumerable<Employe> coll = 
 Employeecollection.DistinctBy(employee => new {employee.fName, employee.lName});

Anonymous objects have correct implementation for both GetHashCodeand Equalsmethods.

匿名对象对GetHashCodeEquals方法都有正确的实现。

回答by Nikola Mitev

Here is a good tutorial

这是一个很好的教程

    public int GetHashCode(Employe obj)
    {
        return obj.fname.GetHashCode() ^ obj.lname.GetHashCode();
    }

回答by aquaraga

The hashcode implementation is not correct:

哈希码实现不正确:

public override int GetHashCode()
{
    return 13 * fName.GetHashCode() + 7 * lName.GetHashCode();
}

回答by user4996868

public int GetHashCode(Employe obj)
{
    return obj.GetHashCode();
}

For this method, return a hashcode of the properties that you are comparing for equality, instead of the object itself. Comparing the hashcode of the objects will always be false, so your list will never be filtered for duplicates.

对于此方法,返回要比较是否相等的属性的哈希码,而不是对象本身。比较对象的哈希码将始终为false,因此您的列表永远不会因重复而被过滤。

回答by Arash

Also it looks like your comparing by reference instead of content, hence the compare function doesn't work.

此外,看起来您是通过引用而不是内容进行比较,因此比较功能不起作用。

change it to use .Equals() instead of == and it should work. example below:

将其更改为使用 .Equals() 而不是 == ,它应该可以工作。下面的例子:

#region IEqualityComparer<pcf> Members

public bool Equals(Employe x, Employe y)
{
    if (x.fName.Equals(y.fName) && x.lName.Equals(y.lName))
    {
        return true;
    }

    return false;
}

public int GetHashCode(Employe obj)
{
    return obj.GetHashCode();
}

#endregion