加入+ IEqualityComparer <t>和HashCode </t>

时间:2010-04-01 20:51:17

标签: c# linq iequalitycomparer

我正在编写自己的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加入两个列表,例如:

  

Initial = A Word = Ant
  初始= A Word =弧
  初始= B Word =船
  ...

我需要一个比较器,我写道:

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。

因为我想比较最初的我虽然我只需要第一个字母Hash(我错了吗?)

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

如果我把“Ant”和“Ant”加上它们。

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

谢谢。

3 个答案:

答案 0 :(得分:2)

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

var mine = from i in initials
     join w in words on i[0] equals w[0]
     select new {
          Initial = i,
          Words = w
     };

答案 1 :(得分:0)

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

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

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

答案 2 :(得分:0)

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