删除自定义IComparable类中的重复项

时间:2014-05-15 18:01:56

标签: c# linq

我有一个包含组合对标识符的表,我使用它来查找寻找匹配项的CSV文件。我在List中捕获未识别的对,并将它们发送到输出框以供以后添加。我希望输出只出现一次唯一对。该类声明如下:

    public class Unmatched:IComparable<Unmatched>
{
    public string first_code { get; set; }
    public string second_code { get; set; }

    public int CompareTo(Unmatched other)
    {

        if (this.first_code == other.first_code)
        {
            return this.second_code.CompareTo(other.second_code);
        }

        return other.first_code.CompareTo(this.first_code);
    }
 }

关于上述代码的一个注释:这将以反向字母顺序返回,以按字母顺序获取它使用此行:

return this.first_code.CompareTo(other.first_code);

以下是添加它的代码。这是在与数据表元素

进行比较之后
unmatched.Add(new Unmatched() 
{ first_code = fields[clients[global_index].first_match_column]
, second_code = fields[clients[global_index].second_match_column] });

我想从列表中删除第一个代码和第二个代码相等的所有对,即。;

PTC,138A
PTC,138A
PTC,138A
MA9,5A
MA9,5A
MA9,5A
MA63,138A
MA63,138A
MA59,87BM
MA59,87BM

应该成为:

PTC, 138A
MA9, 5A
MA63, 138A
MA59, 87BM

我尝试添加我自己的Equate和GetHashCode,如下所示: http://www.morgantechspace.com/2014/01/Use-of-Distinct-with-Custom-Class-objects-in-C-Sharp.html

我尝试过的SE链接在这里:

How would I distinct my list of key/value pairs

Get list of distinct values in List<T> in c#

Get a list of distinct values in List

所有这些都会返回一个仍然包含所有对的列表。以下是输出列表的当前代码(是的,我知道有两条不同的行,似乎都不起作用):

    parser.Close();
    List<Unmatched> noDupes = unmatched.Distinct().ToList();
    noDupes.Sort();
    noDupes.Select(x => x.first_code).Distinct();

    foreach (var pair in noDupes)
    {
        txtUnmatchedList.AppendText(pair.first_code + "," + pair.second_code + Environment.NewLine);
    }

以下是所请求的Equate / Hash代码:

public bool Equals(Unmatched notmatched)
{

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

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

    //Check whether the UserDetails' properties are equal.  
    return first_code.Equals(notmatched.first_code) && second_code.Equals(notmatched.second_code);
}

// 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 UserName field if it is not null.  
    int hashfirst_code = first_code == null ? 0 : first_code.GetHashCode();

    //Get hash code for the City field.  
    int hashsecond_code = second_code.GetHashCode();

    //Calculate the hash code for the GPOPolicy.  
    return hashfirst_code ^ hashsecond_code;
}

我还看了几个使用查询和元组的答案,老实说我不明白。有人能指出我的来源或答案,解释如何(以及为什么)从自定义列表中获取不同的对吗?

(旁边的问题 - 你能否将一个类声明为IComparable和IEquatable?)

2 个答案:

答案 0 :(得分:4)

问题是您没有实施IEquatable<Unmatched>

public class Unmatched : IComparable<Unmatched>, IEquatable<Unmatched>
仅当您实施EqualityComparer<T>.Default时,

Equals(T)才会使用IEquatable<T>方法。你没有这样做,所以它将改为使用引用相等的Object.Equals(object)

您正在调用的Distinct的重载使用EqualityComparer<T>.Default来比较序列的不同元素是否相等。正如文档所述,返回的比较器使用您的GetHashCode实现来查找可能相同的元素。然后,它使用Equals(T)方法检查是否相等,如果您尚未实施Object.Equals(Object)则使用IEquatable<T>

您有Equals(Unmatched)方法,但由于您未实施IEquatable<Unmatched>,因此不会使用该方法。相反,使用默认的Object.Equals方法,该方法使用引用相等。

请注意,您当前的Equals方法未覆盖Object.Equals,因为它需要Object参数,您需要指定override修饰符。

答案 1 :(得分:0)

有关使用Distinct的示例,请参阅here

您必须实施IEqualityComparer<TSource>而不是IComparable<TSource>