【问题标题】:IEnumerable.Intersect does not return all values that matchIEnumerable.Intersect 不返回所有匹配的值
【发布时间】:2015-09-09 07:53:15
【问题描述】:

我有两个列表List<MyClass>

public class MyClass : IEquatable<MyClass>
{
    public string AccountNumber { get; set; }
    public int ID { get; set; }
    public int AccountType { get; set; }

    public bool Equals(MyClass other)
    {
        if (other == null) return false;
        if (object.ReferenceEquals(this, other))
            return true;
        return AccountNumber.Equals(other.AccountNumber) && AccountType.Equals(other.AccountType);
    }

    public override int GetHashCode()
    {
        int hashAccountNumber = AccountNumber == null ? 0 : AccountNumber.GetHashCode();
        int hashType = AccountType.GetHashCode();
        return hashAccountNumber ^ hashType;
    }
}

如果我使用以下代码

var list1 = new List<MyClass>()
{
    new MyClass() { AccountNumber = "1", AccountType = 1, ID = 1}, 
    new MyClass() { AccountNumber = "1", AccountType = 1, ID = 2},
    new MyClass() { AccountNumber = "2", AccountType = 1, ID = 3},
    new MyClass() { AccountNumber = "3", AccountType = 1, ID = 4}
};

var list2 = new List<MyClass>()
{
    new MyClass() { AccountNumber = "1", AccountType = 1, ID = 1 }
};

var alist = list1.Intersect(list2).ToList();

alist 只有 1 个元素,其中 MyClass.ID == 1。它不返回也匹配的第二个。我也可以反过来 var alist = list2.Intersect(list1).ToList(); 得到同样的结果

我的IEquatable 实现有问题吗?因为我不确定我做错了什么。或者这就是IEnumerable 的工作方式?有没有另一种方法可以用来从 list1 返回所有匹配的元素?我真的希望有:)

【问题讨论】:

  • 旁注:如果你正在实现IEquatable&lt;T&gt;并覆盖GetHashCode,你也应该覆盖Equals(object other)
  • @Damien_The_Unbeliever 我无法覆盖EqualsError 1 'MyClass.Equals(MyClass)': no suitable method found to override 当我添加覆盖时。如果我使用与IEquatable 相同的签名,我不应该覆盖Equals 吗?相反,我使用了类类型,因此我用类类型重载了 Equals。如果您认为它不正确,请告诉我。
  • 您应该有 两个 Equals 方法 - 一个接受您当前拥有的 MyClassother 应该是 Object.Equals(Object) 方法的覆盖。请参阅IEquatable.Equals 的文档中的示例
  • @Jaques BTW 我觉得你的问题是一个 XY 问题。我不明白为什么十字路口不适合你。为什么你想要同一个对象出现两次?
  • 因为对象不是 100% 相同的。我有一个缩短版的课程。仅使用 2 个属性来判断它是否是同一种对象,但其他属性使其唯一。我希望它们都在一个列表中,因为我必须如何构建输出

标签: c# ienumerable


【解决方案1】:

交集是 set 操作set 理解为数据结构!),因此,我不明白为什么您的结果应该包含两次相同的项目。集合是独特元素的集合。

【讨论】:

  • 谢谢,我问是否有解决方案。那么显然我的做法不正确,还有别的方法吗?
  • @Jaques 然后再问一个问题。您是在问您的交集是否按预期完成,但是否做错了......我会问另一个问题,解释您希望在您的域中实现什么。
  • @Marias Is there another way I can use to return ALL matching elements from list1? I really hope there is :)
  • 我没有改变我的问题的意思。我的问题标题描述了我的问题。我问身体里的问题。您没有阅读问题。
  • @Jaques 我读过这个问题,它是关于为什么 intersect 返回一项而不是 2。
【解决方案2】:

正如其他人已经说过的,Intersect 将始终返回两个集合上的不同元素列表。

要实现您想要的,请尝试将Intersect 更改为:

var alist = list1.Where(x => list2.Contains(x)).ToList();

【讨论】:

  • 谢谢。至少你回答了这个问题,而不仅仅是告诉我这不可能发生。
  • @Jaques 没有人告诉这不可能发生,但您的问题标题和正文是关于交叉点的。正如我在一些评论中的回答中所说,如果您认为您当前的问题不适合您正在寻找的内容,您应该问另一个问题......
  • @MatíasFidemraizer:问题从一开始就存在。 我可以使用另一种方法从 list1 返回所有匹配的元素吗?阅读整个内容,而不仅仅是标题。
  • @KasparsOzols 是的,顺便说一句,我不明白为什么有人会抛出几十行来问为什么一个路口不能像 OP 想要的那样工作,并且在最后一句话中,提出了一个非常不同的问题。
  • 您的答案正是我想要的。我在标题中给出了问题陈述,并寻求帮助。你给了我。我的标题和正文是我在交叉路口遇到的问题。我问是否有其他方法可以解决我的问题。
【解决方案3】:

来自MSDN

当枚举该方法返回的对象时,Intersect 枚举first,收集该序列的所有distinct 元素。然后它枚举 second,标记出现在两个序列中的那些元素。最后,标记的元素按照它们被收集的顺序产生。

【讨论】:

  • 谢谢,我问是否有解决方案。那么显然我的做法不正确,还有别的方法吗?
【解决方案4】:

试试这个,这段代码不会浪费你的 Equals 方法:

var alist = list1.Where(m => list2.Any(n => n.Equals(m)));

【讨论】:

    猜你喜欢
    • 2018-12-21
    • 2012-11-22
    • 1970-01-01
    • 1970-01-01
    • 2013-04-04
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    • 1970-01-01
    相关资源
    最近更新 更多