我正在编写自己的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”加上它们。
简而言之,这样做的方式是什么?我知道我做错了什么。
谢谢。
答案 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); 这对我有用。