2

我正在编写自己的 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"};

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

初始=A 字=蚂蚁
初始=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();
    }
}

加入本身:

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”,它会同时添加。

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

谢谢你。

4

3 回答 3

2

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

var mine = from i 的首字母
     在 i[0] 上的单词中加入 w 等于 w[0]
     选择新的{
          初始 = i,
          单词 = w
     };
于 2010-04-01T21:17:29.330 回答
0

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

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

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

于 2010-04-01T21:12:04.303 回答
0

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

于 2010-04-01T21:40:42.603 回答