“模糊匹配”并不是指 Levenshtein 距离或其他类似的字符串相似性,而是 TextMate/Ido/Icicles 中使用的方式:给定一组字符串,找到那些包括搜索字符串中所有字符(可能有其他字符在它们之间),并优先选择最佳匹配的字符串。
“模糊匹配”并不是指 Levenshtein 距离或其他类似的字符串相似性,而是 TextMate/Ido/Icicles 中使用的方式:给定一组字符串,找到那些包括搜索字符串中所有字符(可能有其他字符在它们之间),并优先选择最佳匹配的字符串。
我终于明白你在寻找什么了。这个问题很有意思,但是看到你找到的两种算法,似乎人们对规范有着广泛不同的意见;)
我认为更清晰地陈述问题和要求会很有用。
问题:
我们正在寻找一种通过允许用户只输入少数字母来加快输入速度的方法,以便为他们提供一个列表供选择他们真正想要键入的关键词。
分析:
前两个要求可以这样总结:对于输入的axg
,我们要查找与该正则表达式匹配的单词[^a]*a[^x]*x[^g]*g.*
第三个要求是故意的。列表中单词的出现顺序需要保持一致 ... 但是很难猜测评分方法是否比按字母顺序更好。如果列表非常长,则采用评分方法可能更好,但是对于短列表来说,眼睛更容易在明显排序的列表中查找特定项。
此外,按字母顺序具有一致性优势:即添加一个字母不会完全重新排序列表(令人痛苦的眼睛和大脑),它只过滤掉不再匹配的项目。
关于处理Unicode字符没有精度,例如à
是否类似于a
或另一个不同的字符?由于我不知道目前哪种语言在其关键字中使用这些字符,所以暂时不考虑。
我的解决方案:
针对任何输入,我都会构建先前表达的正则表达式。它适用于Python,因为该语言已经具有不区分大小写的匹配功能。
然后,我将匹配我的(按字母顺序排列的)关键词列表,并将其输出进行过滤。
伪代码如下:
WORDS = ['Bar', 'Foo', 'FooBar', 'Other']
def GetList(input, words = WORDS):
expr = ['[^' + i + ']*' + i for i in input]
return [w for w in words if re.match(expr, w, re.IGNORECASE)]
我本可以用一行代码,但是觉得那样会使代码变得晦涩难懂 ;)
这种解决方案在增量情况下非常有效(即当您按照用户类型匹配并因此不断重建时),因为当用户添加字符时,您只需简单地重新过滤刚刚计算出的结果即可。 因此:
我还应该指出,这个正则表达式不涉及回溯,因此非常高效。 它也可以被建模为一个简单的状态机。
http://excellerando.blogspot.com/2010/03/vlookup-with-fuzzy-matching-to-get.html
当然,这是使用Visual Basic for Applications编写的。请小心操作,备上十字架和大蒜:
公共函数SumOfCommonStrings(_ ByVal s1 As String,_ ByVal s2 As String,_ Optional Compare As VBA.VbCompareMethod = vbTextCompare,_ Optional iScore As Integer = 0 _ )作为整数{
"c" => {
0 => [0]
},
"o" => {
0 => [1, 5],
1 => [1]
},
"n" => {
0 => [2]
},
"t" => {
0 => [3]
},
"r" => {
0 => [4, 9]
},
"l" => {
0 => [6, 7],
1 => [4]
},
"e" => {
0 => [9],
1 => [3],
2 => [2]
},
"m" => {
1 => [0]
},
"d" => {
1 => [2]
},
"v" => {
2 => [0]
},
"i" => {
2 => [1]
},
"w" => {
2 => [3]
}
}
{
character-1 => {
word-index-1 => [occurrence-1, occurrence-2, occurrence-n, ...],
word-index-n => [ ... ],
...
},
character-n => {
...
},
...
}
现在正在查找字符串"oe":
{0 => 1, 1 => 1}
。{0 => 9, 1 => 3}
。现在通过查看我们累积的映射中的键,我们知道哪些字符串匹配了模糊搜索。
理想情况下,如果搜索是在用户键入时进行的,您将跟踪结果的累积哈希,并将其传回您的搜索函数。我认为这比迭代所有搜索字符串并在每个字符串上执行完全通配符搜索要快得多。
有趣的是,如果您只关心插入而不是替换或删除,那么您还可以有效地存储每个匹配的Levenstein距离。虽然也许添加这种逻辑并不难。
我最近也遇到了同样的问题。我的解决方案是将连续匹配的字母字符串打分,并排除不按顺序包含键入字母的字符串。
我在这里详细记录了算法:http://blog.kazade.co.uk/2014/10/a-fuzzy-filename-matching-algorithm.html