【问题标题】:Removing duplicates from a List or HashSet in c#从 C# 中的 List 或 HashSet 中删除重复项
【发布时间】:2013-04-16 17:25:20
【问题描述】:

我有一个非常简单的测试方法,它返回一个包含许多重复项的列表,但是当它没有时,我想我会尝试 HashSet,因为它应该删除重复项,但看来我需要覆盖 Equals 和 GetHashCode但我真的很难理解我需要做什么。请多多指教。

HashSet<object> test = XmlManager.PeriodHashSet(Server.MapPath("../Xml/XmlFile.xml"));
foreach (Object period in test2)
{
    PeriodData pd = period as PeriodData;
    Response.Write(pd.PeriodName + "<br>");
}

我也试过了

List<object> test = XmlManager.PeriodList(Server.MapPath("../Xml/XmlFile.xml"));
List<object> test2 = test.Distinct().ToList();
foreach (Object period in test2)
{
    PeriodData pd = period as PeriodData;
    Response.Write(pd.PeriodName + "<br>");
}

PeriodData 对象的 decarewd 如下:

public class PeriodData
{
    private int m_StartYear = -9999999;
    private int m_EndYear = -9999999;
    private string m_PeriodName = String.Empty;

    public int StartYear
    {
        get { return m_StartYear; }
        set { m_StartYear = value; }
    }
    public int EndYear
    {
        get { return m_EndYear; }
        set { m_EndYear = value; }
    }
    public string PeriodName
    {
        get { return m_PeriodName; }
        set { m_PeriodName = value; }
    }
}

这是我要删除重复的返回的 PeriodName。

【问题讨论】:

标签: c# list hashset duplicate-removal


【解决方案1】:

要使HashSet&lt;T&gt; 工作,您至少需要覆盖Object.EqualsObject.GetHashCode。这就是允许散列算法知道是什么让两个对象在值上“不同”或相同的原因。

在简化和改进代码方面,我建议进行两项主要更改以使其工作:

首先,您应该使用HashSet&lt;PeriodData&gt;(或List&lt;PeriodData&gt;),而不是HashSet&lt;object&gt;

其次,您的 PeriodData 类应实现 IEquatable&lt;PeriodData&gt; 以提供正确的散列和相等性。

【讨论】:

  • 但实际上,虽然您提出的建议会改进代码,但只需覆盖 Equals 和 GetHashCode 即可解决问题,无需更改类型参数,也无需实现 IEquatable&lt;&gt;
  • 我的重点是改进,但我不明白覆盖以及如何编写它们。
  • 感谢@ReedCopsey,我采纳了您和其他人的观点并使其发挥了作用。
【解决方案2】:

你必须决定是什么让两个时期相等。如果两个周期的所有三个属性必须相同才能相等,那么您可以这样实现 Equals:

public override bool Equals(object obj)
{
    if (ReferenceEquals(null, obj)) return false;
    if (ReferenceEquals(this, obj)) return true;
    if (obj.GetType() != this.GetType()) return false;
    PeriodData other = (PeriodData)obj;
    return m_StartYear == other.m_StartYear && m_EndYear == other.m_EndYear && string.Equals(m_PeriodName, other.m_PeriodName);
}

对于 GetHashCode,您可以这样做:

    public override int GetHashCode()
    {
        return (((m_StartYear * 397) ^ m_EndYear) * 397) ^ m_PeriodName.GetHashCode();
    }

(归功于它:这些是从 ReSharper 的代码生成工具生成的代码改编而来的。)

正如其他人所指出的,最好也实现IEquatable&lt;T&gt;

如果不能修改类,或者不想修改,可以将等式比较逻辑放在另一个实现IEqualityComparer&lt;PeriodData的类中,传递给HashSet&lt;PeriodData&gt;和@987654326的相应构造函数@

【讨论】:

  • 太棒了,它成功了。我只需要检查 PeriodName 是否相等,以便修改以适应。我还没有实现 IEquitable,因为作为一个相对笨拙的程序员,这对我来说更难理解。我还没有找到一个简单的解释,所以我暂时搁置它。
【解决方案3】:

您必须实现 IEquatable&lt;T&gt; 才能使 Distinct() 工作。

如果你不知道,框架怎么知道“这两个对象是相同的”?您必须为框架提供一种比较对象的方法,这就是 IEquatable&lt;T&gt; 实现的目的。

【讨论】:

  • 覆盖 Equals 和 GetHashCode 可以解决问题。实现IEquatable&lt;&gt;是个好主意,但不是必须的。
猜你喜欢
  • 2012-09-28
  • 1970-01-01
  • 2014-11-11
  • 2010-09-08
  • 1970-01-01
  • 2011-10-21
  • 2019-10-13
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多