如何删除包含数组任意元素的子字符串

3

我有:

str ="this is the string "

我有一个字符串数组:

array =["this is" ,"second element", "third element"]

我希望能够处理字符串,使得移除数组中任意元素对应的子字符串,并返回剩余的字符串。我希望获得以下输出结果:
output: "the string "

我该怎么做呢?

我认为你应该研究一下正则表达式(Regex)。它们可以完美地解决你所寻找的问题。 - Sean
定义“子字符串匹配”。您是指真正的子字符串,还是希望尊重单词边界,以便仅匹配完整的单词? - the Tin Man
3个回答

6

您没有说明您需要真正的子字符串匹配还是在单词边界处进行子字符串匹配。这是有区别的。以下是如何在考虑单词边界的情况下实现它:

str = "this is the string "
array = ["this is" ,"second element", "third element"]
pattern = /\b(?:#{ Regexp.union(array).source })\b/ # => /\b(?:this\ is|second\ element|third\ element)\b/

str[pattern] # => "this is"
str.gsub(pattern, '').squeeze(' ').strip # => "the string"

以下是关于unionunion.source的最新情况:

(简介)

Regexp.union(array) # => /this\ is|second\ element|third\ element/
Regexp.union(array).source # => "this\\ is|second\\ element|third\\ element"

source 返回的数组已经拼接好了,可以更轻松地用于 Regex 创建模式,而不会在模式中注入空洞。考虑以下差异以及它们在模式匹配中可能产生的影响:

/#{ Regexp.union(%w[a . b]) }/ # => /(?-mix:a|\.|b)/
/#{ Regexp.union(%w[a . b]).source }/ # => /a|\.|b/

第一个创建了一个独立的模式,具有自己的大小写、多行和空格优先标志,该模式将嵌入到外部模式中。如果您打算使用子模式,则可能会出现难以跟踪和修复的错误,因此只有当您打算使用子模式时才这样做。

另外,请注意如果您尝试使用以下内容会发生什么:

/#{ %w[a . b].join('|') }/ # => /a|.|b/

生成的模式中嵌入了通配符.,这会破坏您的模式,导致它匹配任何内容。不要这样做。

如果我们不告诉正则表达式引擎遵守单词边界,则可能会发生意外/不良/可怕的事情:

str = "this isn't the string "
array = ["this is" ,"second element", "third element"]
pattern = /(?:#{ Regexp.union(array).source })/ # => /(?:this\ is|second\ element|third\ element)/

str[pattern] # => "this is"
str.gsub(pattern, '').squeeze(' ').strip # => "n't the string"

在处理包含完整单词的子字符串时,以单词为单位思考非常重要。搜索引擎无法区分其中差异,因此需要告诉它应该如何处理。这是许多没有进行过文本处理的人经常忽略的情况。


5

以下是一种方法 -

array =["this is" ,"second element", "third element"]
str = "this is the string "
str.gsub(Regexp.union(array),'') # => " the string "

为了支持不区分大小写,可以使用以下代码: str.gsub(/#{array.join('|')}/i,'')

0

我看到了两种解决方案,起初我更喜欢Brad的。但是我认为这两种方法非常不同,所以一定会有性能差异,因此我创建了下面的文件并运行它。

require 'benchmark/ips'

str = 'this is the string '
array =['this is' ,'second element', 'third element']

def by_loop(str, array)
  array.inject(str) { |result , substring| result.gsub substring, ''  }
end

def by_regex(str, array)
  str.gsub(Regexp.union(array),'')
end

def by_loop_large(str, array)
  array = array * 100
  by_loop(str, array)
end

def by_regex_large(str, array)
  array = array * 100
  by_regex(str, array)
end

Benchmark.ips do |x|
  x.report("loop")  { by_loop(str, array) }
  x.report("regex") { by_regex(str, array) }
  x.report("loop large")  { by_loop_large(str, array) }
  x.report("regex large") { by_regex_large(str, array) }
end

结果:

-------------------------------------------------
            loop    16719.010.4%) i/s -      83888 in   5.073791s
           regex    18701.54.2%) i/s -      94554 in   5.063600s
      loop large      182.60.5%) i/s -        918 in   5.027865s
     regex large      330.90.6%) i/s -       1680 in   5.076771s

结论:
当数组变大时,Arup的方法更加高效。
至于Tin Man对文本中单引号的担忧,我认为这很重要,但这应该是OP的责任而不是当前算法的责任。而且这两种方法在该字符串上产生相同的结果。

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