使用 Linq 与自定义 IEqualityComparer 相交 [英] Intersect with a custom IEqualityComparer using Linq

查看:33
本文介绍了使用 Linq 与自定义 IEqualityComparer 相交的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

长话短说:我有 2 个对象集合.一个包含好的值(我们称之为好"),另一个包含默认值(默认"先生).我想要 Good 和 Default 以及 Default 之间联合的交集.换句话说:Intersect(Union(Good, Default), Default).有人可能认为它解析为默认值,但这里是它变得棘手的地方:我使用自定义 IEqualityComparer.

Long story short: I have 2 collections of objects. One contains good values (Let's call it "Good"), the other default values (Mr. "Default"). I want the Intersect of the Union between Good and Default, and Default. In other words: Intersect(Union(Good, Default), Default). One might think it resolves as Default, but here is where it gets tricky : I use a custom IEqualityComparer.

我有以下课程:

class MyClass
{
    public string MyString1;
    public string MyString2;
    public string MyString3;
}

class MyEqualityComparer : IEqualityComparer<MyClass>
{
    public bool Equals(MyClass item1, MyClass item2)
    {
        if(item1 == null && item2 == null)
            return true;
        else if((item1 != null && item2 == null) ||
                (item1 == null && item2 != null))
            return false;

        return item1.MyString1.Equals(item2.MyString1) &&
               item1.MyString2.Equals(item2.MyString2);
    }

    public int GetHashCode(MyClass item)
    {
        return new { item.MyString1, item.MyString2 }.GetHashCode();
    }
}

以下是我收藏的 Good 和 Default 收藏的特点:

Here are the characteristic of my collections Good and Default collections :

默认值:这是一个很大的集合,包含所有想要的 { MyString1, MyString2 } 对,但 MyString3 的值是您可以猜到的默认值.

Default : It's a large set, containing all the wanted { MyString1, MyString2 } pairs, but the MyString3 values are, as you can guess, default values.

Good :这是一个较小的集合,主要包含默认集合中的项目,但具有一些不错的 MyString3 值.它还有一些 { MyString1, MyString2 } 在想要的集合之外.

Good : It's a smaller set, containing mostly items which are in the Default set, but with some good MyString3 values. It also has some { MyString1, MyString2 } that are outside of the wanted set.

我想要做的是:仅从 Good 中取出 Default 中的项目,但将 Default 中的其他项目添加到其中.

What I want to do is this : Take only the items from Good that are in Default, but add the other items in Default to that.

这是,我认为是,我最好的尝试:

Here is, what I think is, my best try :

HalfWantedResult = Good.Union(Default, new MyEqualityComparer());
WantedResult= HalfWantedResult.Intersect(Good, new MyEqualityComparer());

我教过它应该有效,但我得到的结果基本上只是好的 { MyString1, MyString2 } 对集,但都来自默认集,所以我整个都有默认值.我也尝试切换最后一个 Intersect 的 Default 和 Good,但我得到了相同的结果.

I taught it should have worked, but the result I get is basically only the good { MyString1, MyString2 } pairs set, but all coming from the Default set, so I have the default value all across. I also tried switching the Default and Good of the last Intersect, but I get the same result.

推荐答案

首先这是错误的:

public bool Equals(MyClass item1, MyClass item2)
{
    return GetHashCode(item1) == GetHashCode(item2);
}

如果hashcode不同,则对应的2项肯定不同,但如果相等,则不能保证对应的2项相等.

If the hashcode's are different for sure the corresponding 2 items are different, but if they're equal is not guaranteed that the corresponding 2 items are equal.

所以这是正确的 Equals 实现:

So this is the correct Equals implementation:

public bool Equals(MyClass item1, MyClass item2)
{
    if(object.ReferenceEquals(item1, item2))
        return true;
    if(item1 == null || item2 == null)
        return false;
    return item1.MyString1.Equals(item2.MyString1) &&
           item1.MyString2.Equals(item2.MyString2);
}

建议休闲裤(期待我)代码如下:

As Slacks suggested (anticipating me) the code is the following:

var Default = new List<MyClass>
{
    new MyClass{MyString1="A",MyString2="A",MyString3="-"},
    new MyClass{MyString1="B",MyString2="B",MyString3="-"},
    new MyClass{MyString1="X",MyString2="X",MyString3="-"},
    new MyClass{MyString1="Y",MyString2="Y",MyString3="-"},
    new MyClass{MyString1="Z",MyString2="Z",MyString3="-"},

};
var Good = new List<MyClass>
{
    new MyClass{MyString1="A",MyString2="A",MyString3="+"},
    new MyClass{MyString1="B",MyString2="B",MyString3="+"},
    new MyClass{MyString1="C",MyString2="C",MyString3="+"},
    new MyClass{MyString1="D",MyString2="D",MyString3="+"},
    new MyClass{MyString1="E",MyString2="E",MyString3="+"},
};
var wantedResult = Good.Intersect(Default, new MyEqualityComparer())
                       .Union(Default, new MyEqualityComparer());

// wantedResult:
// A A +
// B B +
// X X -
// Y Y -
// Z Z -

这篇关于使用 Linq 与自定义 IEqualityComparer 相交的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆