我有:
str ="this is the string "
我有一个字符串数组:
array =["this is" ,"second element", "third element"]
我希望能够处理字符串,使得移除数组中任意元素对应的子字符串,并返回剩余的字符串。我希望获得以下输出结果:
output: "the string "
我该怎么做呢?
我有:
str ="this is the string "
我有一个字符串数组:
array =["this is" ,"second element", "third element"]
output: "the string "
您没有说明您需要真正的子字符串匹配还是在单词边界处进行子字符串匹配。这是有区别的。以下是如何在考虑单词边界的情况下实现它:
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"
union
和union.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"
在处理包含完整单词的子字符串时,以单词为单位思考非常重要。搜索引擎无法区分其中差异,因此需要告诉它应该如何处理。这是许多没有进行过文本处理的人经常忽略的情况。
以下是一种方法 -
array =["this is" ,"second element", "third element"]
str = "this is the string "
str.gsub(Regexp.union(array),'') # => " the string "
str.gsub(/#{array.join('|')}/i,'')
我看到了两种解决方案,起初我更喜欢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.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