两个字符串几乎相等

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。

【讨论】:

以上是关于两个字符串几乎相等的主要内容,如果未能解决你的问题,请参考以下文章

断言两个字典几乎相等

判断两个字符串是不是相等 正解的表达方式是

Java中怎么比较两个字符串是不是相等?

在js中怎么判断两个字符串相等?

C++中判断两个字符串是不是相等,怎么判断

JAVA比较两个字符串是不是相等用啥