代码之家  ›  专栏  ›  技术社区  ›  Jesus Rodriguez

join+iequalitycomparer<t>和hashcode

  •  2
  • Jesus Rodriguez  · 技术社区  · 15 年前

    我在写我自己的linq引用,但是我遇到了一些更复杂的操作符实现的问题。

    有一个join实现需要一个iequalitycomparer im变得疯狂。

    在我写作之前,我试图先理解它(显然)

    想象一下这两个列表:

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

    连接本身:

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

    这是我第一次使用hashcode,经过一段很好的调试之后,我看到每个单词都进入比较器并查看它的hashcode,如果另一个单词有它调用的相同hashcode等于。

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

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

    如果我把“蚂蚁”和“蚂蚁”加在一起。

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

    谢谢您。

    3 回复  |  直到 15 年前
        1
  •  0
  •   juharr    15 年前

    如crispy所说,试试 x〔0〕==y〔0〕 而不是 x.开始与(y); 这对我很有用。

        2
  •  2
  •   Crispy    15 年前

    实际上,您不需要自己的相等比较器,只需加入单个字母,如下所示:

    var mine = from i in initials
         join w in words on i[0] equals w[0]
         select new {
              Initial = i,
              Words = w
         };
        3
  •  0
  •   Daniel Pratt    15 年前

    我不知道你为什么会看到这种行为,但我认为使用“selectmany”将是一种更直接的方法,而且(更重要的是)有你想要的行为:

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

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