C# 用于模糊查找的字典哈希函数

C# 用于模糊查找的字典哈希函数,c#,dictionary,hash,hashtable,fuzzy-search,C#,Dictionary,Hash,Hashtable,Fuzzy Search,当需要字符串之间的近似比较时,basic可以提供帮助。它测量要与另一个字符串相等所需的字符串修改量: "aaaa" vs "aaab" => 1 "abba" vs "aabb" => 2 "aaaa" vs "a" => 3 使用词典时可以提供自定义IEqualityComparer。可以将Levenshtein距离作为IEqualityComparer: 我不认为有一个哈希函数可以在你的情况下工作 问题是,您必须仅基于单个值分配bucket,而您无法知道之前添加了什

当需要字符串之间的近似比较时,basic可以提供帮助。它测量要与另一个字符串相等所需的字符串修改量:

"aaaa" vs "aaab" => 1
"abba" vs "aabb" => 2
"aaaa" vs "a"    => 3
使用
词典时
可以提供自定义
IEqualityComparer
。可以将Levenshtein距离作为
IEqualityComparer


我不认为有一个哈希函数可以在你的情况下工作

问题是,您必须仅基于单个值分配bucket,而您无法知道之前添加了什么。但是被散列项的Levenshtein距离可以是从0到“无穷大”的任何值,唯一重要的是它与什么进行比较。因此,您不能满足哈希函数的第二个条件(使相等的对象具有相同的哈希代码)

另一个参数“伪证明”是当您希望最大距离为2并且词典中已有两个项目,它们的相互距离为3时的情况。如果然后添加一个字符串,该字符串与第一个项目之间的距离为2,与第二个项目之间的距离为1,您将如何决定该字符串与哪个项目匹配?这两项都满足您的最大要求,但它可能应该与第二项匹配,而不是与第一项匹配。但是不知道字典的内容,你就不知道如何正确地散列它


对于第二个问题,使用默认的
string.GetHashCode()
方法确实可以提高性能,但会破坏相等比较器的功能。如果在示例代码上测试此解决方案,您可以看到
dict
现在将包含两个键。这是因为
GetHashCode
返回了两个不同的散列码,因此没有冲突,
dict
现在有两个存储桶,并且您的
Equals
方法甚至没有执行。

我可以理解模糊查找。但不是模糊存储。为“aab”赋值时,为什么要覆盖“aaa”?如果你想要的只是模糊查找,那么最好有一个普通的字典,它有一个扩展来进行模糊查找,比如

public static class DictionaryExtensions
{
    public static IEnumerable<T> FuzzyMatch<T>(this IDictionary<string, T> dictionary, string key, int distance = 2)
    {
        IEqualityComparer<string> comparer = new LevenshteinStringComparer(distance);

        return dictionary
            .Keys
            .Where(k => comparer.Equals(k, key))
            .Select(k => dictionary[k]);
    }
}
你明白要点了吗?i、 e显然,以下情况不可能属实

abba == cbbc && 
cddc == cbbc &&
abba != cddc

我看到了一个问题。如果你允许距离为1,并且已经有了一个带有“aab”的项目,加上“aaa”或“abb”的结果是一样的,但是如果第一个项目是“abb”,最终的结果是不同的。这提醒了我——当你绕过一个大障碍物,比如山脉或海洋时,作为生活在相邻区域的动物物种仍然可以交配,你最终可能会让最后两只动物在环的两端无法交配。两种动物在什么时候不再是同一物种而变成不同的物种?你的钥匙也一样。我可以从两个你认为不一样的键开始,但我可以找到一系列中间键,它们被认为是连接前两个键的匹配项。这不是重复项,但我认为这个讨论涉及到@PepitoSh是的,这本字典在很多方面都很奇怪,但是你提到的东西违反了我们应该遵循的一些具体的实现规则吗?一点也不。我的世界更具确定性,我看不出这类词典有什么用处。也许你带来了一些潜在的用例。哦,是的,没有检查使用字符串哈希函数时创建的字典键。回答得很好,这很有帮助:-)。快乐编码!
public int GetHashCode(string obj)
    => obj.GetHashCode();
public static class DictionaryExtensions
{
    public static IEnumerable<T> FuzzyMatch<T>(this IDictionary<string, T> dictionary, string key, int distance = 2)
    {
        IEqualityComparer<string> comparer = new LevenshteinStringComparer(distance);

        return dictionary
            .Keys
            .Where(k => comparer.Equals(k, key))
            .Select(k => dictionary[k]);
    }
}
"abba" vs "cbbc" => 2
"cddc" vs "cbbc" => 2
"abba" vs "cddc" => 4
abba == cbbc && 
cddc == cbbc &&
abba != cddc