我需要一种方法来比较多个字符串到一个测试字符串,并返回与它非常相似的字符串:

TEST STRING: THE BROWN FOX JUMPED OVER THE RED COW

CHOICE A   : THE RED COW JUMPED OVER THE GREEN CHICKEN
CHOICE B   : THE RED COW JUMPED OVER THE RED COW
CHOICE C   : THE RED FOX JUMPED OVER THE BROWN COW

(如果我做对了)最接近“TEST string”的字符串应该是“CHOICE C”。最简单的方法是什么?

我计划将其实现为多种语言,包括VB.net、Lua和JavaScript。此时,伪代码是可以接受的。如果你能提供一个特定语言的例子,这也是非常感谢的!


当前回答

我怀疑选项B更接近测试字符串,因为它距离原始字符串只有4个字符(和2个删除)。而C更接近,因为它同时包含棕色和红色。但是,它有一个更大的编辑距离。

有一种叫做Levenshtein Distance的算法可以测量两个输入之间的编辑距离。

这里有一个算法工具。

选择A的距离是15。 选择B的距离是6。 选择C的距离为9。

编辑:对不起,我一直在levenshtein工具混合字符串。更新到正确的答案。

其他回答

Lua实现,为子孙后代:

function levenshtein_distance(str1, str2)
    local len1, len2 = #str1, #str2
    local char1, char2, distance = {}, {}, {}
    str1:gsub('.', function (c) table.insert(char1, c) end)
    str2:gsub('.', function (c) table.insert(char2, c) end)
    for i = 0, len1 do distance[i] = {} end
    for i = 0, len1 do distance[i][0] = i end
    for i = 0, len2 do distance[0][i] = i end
    for i = 1, len1 do
        for j = 1, len2 do
            distance[i][j] = math.min(
                distance[i-1][j  ] + 1,
                distance[i  ][j-1] + 1,
                distance[i-1][j-1] + (char1[i] == char2[j] and 0 or 1)
                )
        end
    end
    return distance[len1][len2]
end

关于这类算法,一个非常非常好的资源是Simmetrics: http://sourceforge.net/projects/simmetrics/

不幸的是,包含大量文档的很棒的网站已经消失了:( 以防它再次出现,它之前的地址是这样的: http://www.dcs.shef.ac.uk/~sam/simmetrics.html

瞧(由“时光倒流机”提供):http://web.archive.org/web/20081230184321/http://www.dcs.shef.ac.uk/~sam/simmetrics.html

你可以研究一下源代码,有几十种算法可以进行这种比较,每一种都有不同的权衡。这些实现是用Java实现的。

如果输入数据太大(比如数百万个字符串),这个问题就很难实现。我用弹性搜索来解决这个问题。

快速入门:https://www.elastic.co/guide/en/elasticsearch/client/net-api/6.x/elasticsearch-net.html

只需将所有输入数据插入到DB中,您就可以根据任何编辑距离快速搜索任何字符串。下面是一个c#代码片段,它会给你一个按编辑距离排序的结果列表(从小到大)

var res = client.Search<ClassName>(s => s
    .Query(q => q
    .Match(m => m
        .Field(f => f.VariableName)
        .Query("SAMPLE QUERY")
        .Fuzziness(Fuzziness.EditDistance(5))
    )
));

如果您在搜索引擎上下文中执行此操作,或者在数据库前端执行此操作,则可以考虑使用类似Apache Solr的工具,并使用ComplexPhraseQueryParser插件。这种组合允许您搜索字符串索引,并根据相关性(由Levenshtein距离确定)对结果进行排序。

当传入的查询可能有一个或多个拼写错误时,我们一直在对大量艺术家和歌曲标题的集合使用它,并且它工作得非常好(考虑到集合包含数百万个字符串,它的速度非常快)。

此外,使用Solr,您可以根据需要通过JSON根据索引进行搜索,因此不必在不同的语言之间重新设计解决方案。

你可能会对这篇博客感兴趣。

http://seatgeek.com/blog/dev/fuzzywuzzy-fuzzy-string-matching-in-python

Fuzzywuzzy是一个Python库,它提供了简单的距离度量,例如用于字符串匹配的Levenshtein距离。它构建在标准库中的difflib之上,并将使用Python-levenshtein(如果可用的话)的C实现。

http://pypi.python.org/pypi/python-Levenshtein/