【问题标题】:Join + IEqualityComparer<T> and HashCode加入 + IEqualityComparer<T> 和 HashCode
【发布时间】:2010-04-02 05:40:42
【问题描述】:

我正在编写自己的 LINQ 参考,但在一些更复杂的运算符实现方面遇到了麻烦。

有一个 Join 实现需要一个 IEqualityComparer 我快疯了。

我想在写之前先理解它(显然)

图像这两个列表:

List<string> initials = new List<string> {"A", "B", "C", "D", "E"};

List<string> words = new List<string> {"Ant", "Crawl", "Pig", "Boat", "Elephant", "Arc"};

这里没有什么奇怪的。我想通过首字母加入这两个列表,例如:

首字母=A Word=Ant
首字母=A 字=弧
首字母=B 字=船
...

我需要一个比较器,我写了这个:

public class InitialComparator : IEqualityComparer<string>
{
    public bool Equals(string x, string y)
    {
        return x.StartsWith(y);
    }

    public int GetHashCode(string obj)
    {
        return obj[0].GetHashCode();
    }
}

Join 本身:

var blah = initials.Join(words,
                                  initial => initial,
                                  word => word,
                                  (initial, word) =>
                                  new {Initial = initial, Word = word},
                                  new InitialComparator());

这是我第一次使用 HashCodes,经过一段良好的调试后,我看到每个单词都进入比较器并查看其 HashCode,如果另一个单词具有相同的 HashCode,则它调用 equals。

由于我只想比较最初的我,虽然我只需要第一个字母哈希(我错了吗?)

问题是这不能正常工作。它说“Ant”和“Arc”是相等的,好的,它比较同一个列表中的每个单词,但它只添加它找到的最后一个单词,在这种情况下Arc,忽略Ant和Ant等于“A "也...

如果我输入“Ant”和“Ant”,它会同时添加。

简而言之,这样做的方法是什么?我知道我做错了什么。

谢谢。

【问题讨论】:

  • 这不会回答您的问题,但您的 Equals 方法存在缺陷。在您当前的实现中,“Ants”将等于“Ant”,但“Ant”将不等于“Ants”。
  • 不是一个答案,但它是一个很好的评论。很奇怪,你能再解释一下吗?你是对的。它添加了“蚂蚁”和“蚂蚁”。 “Ant”和“Ants”它添加了 Ants 并表示“Ant”和“Ants”是相同的。我不明白为什么。
  • StartsWith 如果实例完全以参数开始,而不仅仅是初始值,则返回 true。另一种说法是,如果参数完全包含在实例中并且位于实例的开头,则返回true。所以 "Ant".StartsWith("Ants") 是假的,因为 's' 在实例中不存在。
  • 这就是我的解决方案。如果您将其作为答案,我会将其标记为有效。

标签: c# linq iequalitycomparer


【解决方案1】:

您实际上并不需要自己的相等比较器,只需像这样加入单个字母:

var mine = from i 的首字母
     在 i[0] 上的单词中加入 w 等于 w[0]
     选择新的{
          初始 = i,
          单词 = w
     };

【讨论】:

  • 那么我想你可以修复你的 Equals 方法,但我真的很好奇为什么你必须使用自定义比较器。 ' public bool Equals(string x, string y) { return x[0] == y[0]; } '
  • 我说了两遍。我写了所有实现的所有运算符的参考,其中之一是 Join + 比较器。问题只是 Equals 方法。
【解决方案2】:

正如 Crispy 提到的尝试 x[0] == y[0] 代替 x.StartsWith(y); 这对我有用。

【讨论】:

    【解决方案3】:

    我不确定您为什么会看到这种行为,但我认为使用“SelectMany”会是一种更直接的方法,并且(更重要的是)具有您想要的行为:

    var blah =
        from word in words
        from initial in initials
        where (word.StartsWith(initial))
        select new { Initial = initial, Word = word };
    

    我更喜欢尽可能使用理解语法。当理解查询中有多个“from”子句时,将调用“SelectMany”。

    【讨论】:

    • 是的,但正如我所说,我正在用西班牙语编写 LINQ 操作员参考。我现在使用 Join 运算符,我需要一个带有 IEqualityComparer 的 Join 示例。一些简单的东西,如果可能的话不需要更多的操作员。我想了几个小时来做​​一些不是很愚蠢的事情。我以那件事结束,因为它很简单,但我无法让它发挥作用。
    猜你喜欢
    • 2011-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-31
    • 2013-09-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多