加入+ IEqualityComparer和哈希码

发布于 2024-08-27 09:39:10 字数 1460 浏览 5 评论 0原文

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

这里没什么奇怪的。我想按初始值加入两个列表,例如:

首字母=一个词=蚂蚁
初始=一个字=弧
首字母=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,如果另一个单词有它调用 equals 的相同 HashCode。

因为我只想比较首字母,所以我只需要第一个字母哈希(我错了吗?)

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

如果我输入“Ant”和“Ant”,它就会添加两者。

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

谢谢。

Im writing my own LINQ reference but Im getting troubles with some of the more complicated operators implementations.

There is a Join implementation that takes a IEqualityComparer Im getting just crazy.

Im trying to understand it first before I write (obviously)

Image this two lists:

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

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

Nothing weird here. I want to join both lists by the Initial, something like:

Initial=A Word=Ant
Initial=A Word=Arc
Initial=B Word=Boat
...

I need a comparator, I wrote this:

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();
    }
}

The Join itself:

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

It's the first time Im using HashCodes, after a good session of debugging I see that every word go to the comparator and look at its HashCode, if another word has the same HashCode it calls equals.

Since I want to compare just the initial I though that I just need the first letter Hash (Am I wrong?)

The thing is that this is not working correctly. Its says that "Ant" and "Arc" are equals, Ok, its comparing every word in the same list or not, But it adds only the last word it finds, in this case Arc, ignoring Ant and Ant is equals to "A" too...

If I put "Ant" and "Ant" it add both.

In short, What is the way of doing something like that? I know that Im doing something wrong.

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

浪推晚风 2024-09-03 09:39:10

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

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

You don't actually need your own equality comparer, just join on the individual letter like so:

var mine = from i in initials
     join w in words on i[0] equals w[0]
     select new {
          Initial = i,
          Words = w
     };
烂柯人 2024-09-03 09:39:10

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

As Crispy mentioned try
x[0] == y[0]
instead of
x.StartsWith(y);
That worked for me.

美羊羊 2024-09-03 09:39:10

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

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

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

I'm not sure why you're seeing this behavior, but I think using "SelectMany" would be a more straightforward approach and (more importantly) has the behavior you want:

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

I prefer to use the comprehension syntax where possible. "SelectMany" is invoked when there are multiple "from" clauses in a comprehension query.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文