Ruby删除与数组的任何元素匹配的子字符串

时间:2014-05-16 17:00:38

标签: ruby-on-rails ruby arrays string

我有一个字符串str ="this is the string ",我有一个字符串数组

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

我想处理字符串,以便匹配任何数组元素的子字符串应该被删除,其余字符串应该返回。所以我想要以下输出。

output: "the string "

我怎样才能在红宝石中做到这一点。

3 个答案:

答案 0 :(得分: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,'')

答案 1 :(得分:5)

您没有说明是否需要真正的子字符串匹配或字边界处的子字符串匹配。有区别。以下是如何识别单词边界:

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"

在处理包含完整单词的子串时,用词来思考是很重要的。引擎不知道差异,所以你必须告诉它该怎么做。这种情况经常被那些不必进行文本处理的人错过。

答案 2 :(得分:0)

我看到了两种解决方案,起初我更喜欢布拉德的解决方案。但我认为这两种方法是如此不同,以至于必须有性能差异所以我创建了下面的文件并运行它。

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.0 (±10.4%) i/s -      83888 in   5.073791s
           regex    18701.5 (±4.2%) i/s -      94554 in   5.063600s
      loop large      182.6 (±0.5%) i/s -        918 in   5.027865s
     regex large      330.9 (±0.6%) i/s -       1680 in   5.076771s

结论:

当数组变大时,Arup的方法会更有效率。

至于Tin Man对文字中单引号的关注,我认为这非常重要,但这将是OP的责任,而不是当前的算法。这两种方法在该字符串上生成相同的内容。