两个字符串几乎相等
Posted
技术标签:
【中文标题】两个字符串几乎相等【英文标题】:Two strings being almost equal 【发布时间】:2017-09-26 00:01:40 【问题描述】:我定义两个字符串几乎相等如果:
-
它们的长度相同,或者
它们的长度相差一个,字符串相差一个字符。
这:
HOW DO YOU
HO DO YOU
这些:
abcdef
bcdef
但是这些字符串并不几乎相等:
Almost
Anost
这些也不是:
Almost
Aomst
我有这个函数,我试图让它判断两个字符串是否几乎相等:
def str_almost_equal(a, b)
a.downcase == b.downcase || (a.size == b.size && a.downcase.chars.map.with_index|c, i| c == b.downcase[i].count(false) == 1)
end
使用"aaa"
和"aab"
调用上述代码的结果为true
。
如果除上述之外,字符串长度仅相差 1 且字符除 1 外相同,我该如何扩展我的函数以使字符串几乎相等?
【问题讨论】:
为什么代码中有downcase
?这似乎打乱了你的整个意图。
【参考方案1】:
在您的 Gemfile 中使用“模糊字符串匹配”gem:
gem 'fuzzy-string-match'
它真的很容易使用:
2.2.7 :001 > require 'fuzzystringmatch'
=> true
2.2.7 :002 > jarow = FuzzyStringMatch::JaroWinkler.create(:pure)
=> #<FuzzyStringMatch::JaroWinklerPure:0x007fa08c4d8710>
2.2.7 :003 > jarow.getDistance('Almost', 'Aomst')
=> 0.8900000000000001
2.2.7 :004 > jarow.getDistance('Almost', 'Anost')
=> 0.8400000000000001
2.2.7 :005 > jarow.getDistance('Almost', 'Almost')
=> 1.0
我将它用于模糊字符串匹配,它很棒。就我而言,我将文件名与歌曲标题进行匹配,然后进行笛卡尔连接(基本上,将每个文件名与每个标题进行匹配),然后为每个歌曲获取热门歌曲,至少在它们超过某个阈值时.
【讨论】:
我尝试在我的 Gemfile 中包含“fuzzy-string-match”gem,但收到错误消息,“在您的 Gemfile 中列出的任何 gem 源中找不到 gem 'fuzzystringmatch' 或在这台机器” 你必须运行 bundle 来添加 gem。您可以阅读相关文档。 查看其他答案 - 请不要重新发明这个***,除非它是一项学术活动。 Jaro/Winkler 算法和它们一样好,并且已经被编码。使用它来解决更大的问题。【参考方案2】:尝试找出两个字符串的交集。
查看此链接here,它提供了两个字符串之间相同字符的数量。
您可以检查最长字符串的长度,以及它们相交的字符数。
例如如果较长的字符串长度为 n,则交集应为 n-1 以“几乎”相等
【讨论】:
这不起作用。根据您列出的函数 "abc".intersection("ba") 导致非零值,但根据我的定义,它们几乎不相等。 “abc”“几乎”等于“ab”,几乎等于“ac”,但不几乎等于“ca”或“ba”。订购很重要。【参考方案3】:如果顺序不是问题,那么你可以计算字符的集合差异:
def str_almost_equal(a, b)
shortest, longest = [a.chars,b.chars].minmax_by(&:length)
(longest - shortest).length == 1
end
但是,您最后的测试表明顺序确实很重要。所以这更像是一个longest common subsequence 的问题,具有这些特征:
LCS 必须等于较小的字符串(换句话说,小字符串必须完全包含在较大的字符串中,但不一定是连续的) 较大的字符串必须恰好大一个字符所以,给定一个lcs
函数,你可以这样做:
def str_almost_equal(a, b)
shortest, longest = [a,b].minmax_by(&:length)
lcs(a,b) == shortest && longest.length - shortest.length == 1
end
您可以在上面的链接中找到lcs
函数。这是一个:
def lcs(xstr, ystr)
return "" if xstr.empty? || ystr.empty?
x, xs, y, ys = xstr[0..0], xstr[1..-1], ystr[0..0], ystr[1..-1]
if x == y
x + lcs(xs, ys)
else
[lcs(xstr, ys), lcs(xs, ystr)].max_by |x| x.size
end
end
您还可以查看diff-lcs
gem。
【讨论】:
以上是关于两个字符串几乎相等的主要内容,如果未能解决你的问题,请参考以下文章