Ruby比较两个字符串相似度百分比

17

我想在Ruby中比较两个字符串并找到它们的相似度。

我查看了Levenshtein gem,但它似乎是2008年最后更新的,而且我找不到如何使用它的文档。一些博客建议这已经损坏了。

我尝试了text gem和Levenshtein,但它返回一个整数(较小的值更好)。

显然,如果两个字符串的长度不同,我会遇到Levenshtein算法的问题(例如比较两个姓名,其中一个有中间名而另一个没有)。

你会建议我怎么做才能得到百分比比较结果?

编辑:我正在寻找类似于PHP的similar text


可能是重复的问题,与https://dev59.com/jVPTa4cB1Zd3GeqPkpvv相似。请参考该链接。 - Fredrik Pihl
这将生成一个差异列表,我正在寻找相似度的百分比。 - Tarang
如果字符串长度不同,应该以哪个字符串作为计算百分比的基础? - Michael Kohl
长的更好吗?我正在尝试遍历一个名称列表,将其中一个列中的名称与另一个列中最相似的名称匹配(其中一侧的名称具有中间名称或破折号)。 - Tarang
可以使用Levenshtein比较并将其转换为百分比,正如这里建议的那样:https://dev59.com/Imkv5IYBdhLWcg3wtTAN - nazar kuliyev
这里有好的答案:https://dev59.com/lmQo5IYBdhLWcg3wGsLN - Paulo Belo
3个回答

19

我认为您的问题需要一些澄清,但这是一个快速而简单的解决方案(根据您上面的澄清计算作为更长字符串的百分比):

def string_difference_percent(a, b)
  longer = [a.size, b.size].max
  same = a.each_char.zip(b.each_char).count { |a,b| a == b }
  (longer - same) / a.size.to_f
end

我仍然不确定你所寻找的百分比差异有多大意义,但这应该至少能让你开始了解。

它有点像Levensthein距离,因为它会逐个字符比较字符串。因此,如果两个名称仅由中间名不同,它们实际上会非常不同。


有人能解释一下“same”位是什么吗?所以它循环遍历每个字符,而zip为字符串A中的每个字符创建一个数组,并且 - 我期望的是 - 字符串B中的每个字符。第二个each_char如何知道要将索引连接到数组中? - Jack Rothrock
此外,当开头有一个字符更改时,这个计算方法并不有效。 - Jack Rothrock
1
注意在Select中的 a,因为它会清除通过参数传递的变量。最好使用其他字母。same = a.each_char.zip(b.each_char).select{ |c,d| c == d }.size - sesperanto
1
它只是在块内部隐藏它。 - Michael Kohl
1
same = a.each_char.zip(b.each_char).count{ |c,d| c == d } - Navid EMAD
将返回0到1之间的范围。如果是0,则为ico,如果是1,则完全不同。 - Raoni Sporteman

17

现在有一个针对 similar_text 的 Ruby Gem 。https://rubygems.org/gems/similar_text 它提供了一个 similar 方法,用于比较两个字符串,并返回表示两个字符串相似度的百分比。


3
类似文本宝石在处理大字符串时会冻结,尝试过143kb的HTML页面。 - nazar kuliyev

15
我可以推荐使用fuzzy-string-match gem。
你可以像这样使用它(摘自文档):
require "fuzzystringmatch"
jarow = FuzzyStringMatch::JaroWinkler.create(:native)
p jarow.getDistance("jones", "johnson")

它将返回一个分数~0.832,告诉我们这些字符串匹配的好坏程度。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接