首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >linq例外和自定义IEqualityComparer

linq例外和自定义IEqualityComparer
EN

Stack Overflow用户
提问于 2010-03-23 23:11:56
回答 3查看 11.6K关注 0票数 19

我尝试在两个字符串列表上实现一个自定义比较器,并使用.Except() linq方法来获取不在其中一个列表中的字符串。我做自定义比较器的原因是因为我需要做一个“模糊”比较,即一个列表中的一个字符串可以嵌入到另一个列表中的字符串中。

我做了以下比较器

代码语言:javascript
复制
public class ItemFuzzyMatchComparer : IEqualityComparer<string>
{
    bool IEqualityComparer<string>.Equals(string x, string y)
    {
        return (x.Contains(y) || y.Contains(x));
    }

    int IEqualityComparer<string>.GetHashCode(string obj)
    {
        if (Object.ReferenceEquals(obj, null))
            return 0;
        return obj.GetHashCode();
    }
}

当我调试时,唯一命中的断点是在GetHashCode()方法中。Equals()永远不会被触动。有什么想法吗?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2010-03-23 23:13:52

如果返回的所有哈希码都不同,则不需要比较是否相等。

基本上问题是你的散列和相等的概念是非常不同的。我不完全确定您将如何纠正这一点,但在您这样做之前,它肯定不会起作用。

您需要确保如果Equals(a, b)返回true,那么GetHashCode(a) == GetHashCode(b)。(相反的情况不一定是真的-散列冲突是可以接受的,尽管显然您希望它们尽可能少。)

票数 17
EN

Stack Overflow用户

发布于 2010-03-24 00:23:14

正如Jon所指出的,您需要确保两个字符串的哈希码相等(根据您的比较规则)。不幸的是,这相当困难。

为了演示这个问题,Equals(str, "")为所有字符串str返回true,这实际上意味着所有字符串都等于空字符串,因此,所有字符串必须具有与空字符串相同的哈希码。因此,正确实现IEqualityComparer的唯一方法是始终返回相同的散列码:

代码语言:javascript
复制
public class ItemFuzzyMatchComparer : IEqualityComparer<string>  { 
  bool IEqualityComparer<string>.Equals(string x, string y)  { 
    return (x.Contains(y) || y.Contains(x)); 
  }  
  int IEqualityComparer<string>.GetHashCode(string obj)  { 
    if (Object.ReferenceEquals(obj, null)) return 0; 
    return 1; 
  } 
}

然后,您可以使用Except方法,它将正确运行。唯一的问题是你将(可能)得到一个非常低效的实现,所以如果你需要更好的性能,你可能不得不实现你自己的Except。然而,我不能确切地确定LINQ实现的效率会有多低,我也不确定是否有可能为您的比较规则提供任何有效的实现。

票数 6
EN

Stack Overflow用户

发布于 2010-03-25 03:41:12

也许这个问题可以在没有IEqualityComparer接口实现的情况下得到解决。Jon和Thomas在实现该接口方面有很好的观点,而平等似乎不能定义你的问题。根据您的描述,我认为您可以在比较过程中不使用Except扩展来完成此操作。取而代之的是,首先获取匹配,然后执行Except。看看这是否能帮你完成工作:

代码语言:javascript
复制
 List<String> listOne = new List<string>(){"hard", "fun", "code", "rocks"};
 List<String> listTwo = new List<string>(){"fund", "ode", "ard"};

 var fuzzyMatchList = from str in listOne
                      from sr2 in listTwo
                      where str.Contains(sr2) || sr2.Contains(str)
                      select str;
 var exceptList = listOne.Except(fuzzyMatchList);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2501007

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档