Ruby 如何查看一个字符串是否包含关键字列表中的关键字?
我想看看一个字符串是否包含关键字列表中的关键字 我有以下功能:Ruby 如何查看一个字符串是否包含关键字列表中的关键字?,ruby,Ruby,我想看看一个字符串是否包含关键字列表中的关键字 我有以下功能: def needfilter?(src) ["keyowrd_1","keyowrd_2","keyowrd_3","keyowrd_4","keyowrd_5"].each do |kw| return true if src.include?(kw) end false end 这个代码块可以简化成一行句子吗 我知道可以简化为: def needfilter?(src) !
def needfilter?(src)
["keyowrd_1","keyowrd_2","keyowrd_3","keyowrd_4","keyowrd_5"].each do |kw|
return true if src.include?(kw)
end
false
end
这个代码块可以简化成一行句子吗
我知道可以简化为:
def needfilter?(src)
!["keyowrd_1","keyowrd_2","keyowrd_3","keyowrd_4","keyowrd_5"].select{|c| src.include?(c)}.empty?
end
但是,如果关键字数组列表很长,这种方法就没有那么有效。看起来是一个很好的方法用例:
看起来是一个很好的方法用例: 我认为
def need_filter?(src)
(src.split(/ /) & ["keyowrd_1","keyowrd_2","keyowrd_3","keyowrd_4","keyowrd_5"]).empty?
end
将按照您的期望工作(如中所述),并且将比任何?
和包括?
更快,我认为
def need_filter?(src)
(src.split(/ /) & ["keyowrd_1","keyowrd_2","keyowrd_3","keyowrd_4","keyowrd_5"]).empty?
end
def need_filter?(src)
!!(src =~ /keyowrd_1|keyowrd_2|keyowrd_3|keyowrd_4|keyowrd_5/)
end
将按照您的预期工作(如中所述),并且将比任何?
和包括?
更快
def need_filter?(src)
!!(src =~ /keyowrd_1|keyowrd_2|keyowrd_3|keyowrd_4|keyowrd_5/)
end
=~
方法返回fixnum或nil。双重爆炸将其转换为布尔值
=~
方法返回fixnum或nil。双重爆炸将其转换为布尔值。我很好奇什么是最快的解决方案,我创建了一个到目前为止所有答案的基准
我改了一点。出于调优的原因,我只为每个测试创建一次regexp
require 'benchmark'
KEYWORDS = ["keyowrd_1","keyowrd_2","keyowrd_3","keyowrd_4","keyowrd_5"]
TESTSTRINGS = ['xx', 'xxx', "keyowrd_2"]
N = 10_000 #Number of Test loops
def needfilter_orig?(src)
["keyowrd_1","keyowrd_2","keyowrd_3","keyowrd_4","keyowrd_5"].each do |kw|
return true if src.include?(kw)
end
false
end
def needfilter_orig2?(src)
!["keyowrd_1","keyowrd_2","keyowrd_3","keyowrd_4","keyowrd_5"].select{|c| src.include?(c)}.empty?
end
def needfilter_any?(src)
["keyowrd_1","keyowrd_2","keyowrd_3","keyowrd_4","keyowrd_5"].any? do |kw|
src.include? kw
end
end
def needfilter_regexp?(src)
!!(src =~ Regexp.union(KEYWORDS))
end
def needfilter_regexp_init?(src)
!!(src =~ $KEYWORDS_regexp)
end
def needfilter_split?(src)
(src.split(/ /) & KEYWORDS).empty?
end
Benchmark.bmbm(10) {|b|
b.report('orig') { N.times { TESTSTRINGS.each{|src| needfilter_orig?(src)} } }
b.report('orig2') { N.times { TESTSTRINGS.each{|src| needfilter_orig2?(src) } } }
b.report('any') { N.times { TESTSTRINGS.each{|src| needfilter_any?(src) } } }
b.report('regexp') { N.times { TESTSTRINGS.each{|src| needfilter_regexp?(src) } } }
b.report('regexp_init') {
$KEYWORDS_regexp = Regexp.union(KEYWORDS) # Initialize once
N.times { TESTSTRINGS.each{|src| needfilter_regexp_init?(src) } }
}
b.report('split') { N.times { TESTSTRINGS.each{|src| needfilter_split?(src) } } }
} #Benchmark
结果:
Rehearsal -----------------------------------------------
orig 0.094000 0.000000 0.094000 ( 0.093750)
orig2 0.093000 0.000000 0.093000 ( 0.093750)
any 0.110000 0.000000 0.110000 ( 0.109375)
regexp 0.578000 0.000000 0.578000 ( 0.578125)
regexp_init 0.047000 0.000000 0.047000 ( 0.046875)
split 0.125000 0.000000 0.125000 ( 0.125000)
-------------------------------------- total: 1.047000sec
user system total real
orig 0.078000 0.000000 0.078000 ( 0.078125)
orig2 0.109000 0.000000 0.109000 ( 0.109375)
any 0.078000 0.000000 0.078000 ( 0.078125)
regexp 0.579000 0.000000 0.579000 ( 0.578125)
regexp_init 0.046000 0.000000 0.046000 ( 0.046875)
split 0.125000 0.000000 0.125000 ( 0.125000)
如果只创建一次regexp,使用正则表达式的解决方案是最快的。我很好奇什么是最快的解决方案,我创建了一个到目前为止所有答案的基准 我改了一点。出于调优的原因,我只为每个测试创建一次regexp
require 'benchmark'
KEYWORDS = ["keyowrd_1","keyowrd_2","keyowrd_3","keyowrd_4","keyowrd_5"]
TESTSTRINGS = ['xx', 'xxx', "keyowrd_2"]
N = 10_000 #Number of Test loops
def needfilter_orig?(src)
["keyowrd_1","keyowrd_2","keyowrd_3","keyowrd_4","keyowrd_5"].each do |kw|
return true if src.include?(kw)
end
false
end
def needfilter_orig2?(src)
!["keyowrd_1","keyowrd_2","keyowrd_3","keyowrd_4","keyowrd_5"].select{|c| src.include?(c)}.empty?
end
def needfilter_any?(src)
["keyowrd_1","keyowrd_2","keyowrd_3","keyowrd_4","keyowrd_5"].any? do |kw|
src.include? kw
end
end
def needfilter_regexp?(src)
!!(src =~ Regexp.union(KEYWORDS))
end
def needfilter_regexp_init?(src)
!!(src =~ $KEYWORDS_regexp)
end
def needfilter_split?(src)
(src.split(/ /) & KEYWORDS).empty?
end
Benchmark.bmbm(10) {|b|
b.report('orig') { N.times { TESTSTRINGS.each{|src| needfilter_orig?(src)} } }
b.report('orig2') { N.times { TESTSTRINGS.each{|src| needfilter_orig2?(src) } } }
b.report('any') { N.times { TESTSTRINGS.each{|src| needfilter_any?(src) } } }
b.report('regexp') { N.times { TESTSTRINGS.each{|src| needfilter_regexp?(src) } } }
b.report('regexp_init') {
$KEYWORDS_regexp = Regexp.union(KEYWORDS) # Initialize once
N.times { TESTSTRINGS.each{|src| needfilter_regexp_init?(src) } }
}
b.report('split') { N.times { TESTSTRINGS.each{|src| needfilter_split?(src) } } }
} #Benchmark
结果:
Rehearsal -----------------------------------------------
orig 0.094000 0.000000 0.094000 ( 0.093750)
orig2 0.093000 0.000000 0.093000 ( 0.093750)
any 0.110000 0.000000 0.110000 ( 0.109375)
regexp 0.578000 0.000000 0.578000 ( 0.578125)
regexp_init 0.047000 0.000000 0.047000 ( 0.046875)
split 0.125000 0.000000 0.125000 ( 0.125000)
-------------------------------------- total: 1.047000sec
user system total real
orig 0.078000 0.000000 0.078000 ( 0.078125)
orig2 0.109000 0.000000 0.109000 ( 0.109375)
any 0.078000 0.000000 0.078000 ( 0.078125)
regexp 0.579000 0.000000 0.579000 ( 0.578125)
regexp_init 0.046000 0.000000 0.046000 ( 0.046875)
split 0.125000 0.000000 0.125000 ( 0.125000)
如果只创建一次regexp,则使用正则表达式的解决方案是最快的。这是我的方法:
def needfilter?(src)
keywords = Regexp.union("keyowrd_1","keyowrd_2","keyowrd_3","keyowrd_4","keyowrd_5")
!!(src =~ keywords)
end
此解决方案具有:
- 无迭代
- 使用regexp.union的单个regexp
即使是一大组关键字也应该是快速的。请注意,在方法中硬编码关键字并不理想,但我假设这只是为了示例的缘故。我会这样做:
def needfilter?(src)
keywords = Regexp.union("keyowrd_1","keyowrd_2","keyowrd_3","keyowrd_4","keyowrd_5")
!!(src =~ keywords)
end
此解决方案具有:
- 无迭代
- 使用regexp.union的单个regexp
即使是一大组关键字也应该是快速的。请注意,在方法中硬编码关键字并不理想,但我假设这只是为了示例的缘故。src是一个字符串,根据这个问题。我通过将所有字符串拆分为单词来修复它。谢谢,但是这种方法失败了,src字符串可能非常复杂。我认为这不是很有效,因为我只想知道字符串命中任何关键字,如果是,忽略其他关键字,只返回truesrc是字符串,根据问题。我通过将所有字符串拆分为单词来修复它。谢谢,但是这种方法失败了,src字符串可能非常复杂。我认为这不是很有效,因为我只想知道字符串命中了任何关键字,如果是这样,忽略其他关键字并返回true。你也可以用
/{keywords.join('.')}/
构建正则表达式(假设关键字不包含符号)。这可能是最快的解决方案。但是试着对所有答案进行基准测试。你也可以用/#{keywords.join('|')}/
(假设关键字不包含符号)构建正则表达式。这可能是最快的解决方案。但是试着对所有答案进行基准测试。谢谢,你的方法非常好。在我的实际代码中,关键字来自一些额外的配置,这里我只想知道哪个解决方案更好。这就是我的想法。通过只计算一次联合关键字并将结果regexp存储在方法外部(例如属性中),可以节省更多时间。那么您的整个方法定义就是!!(src=~@keywords)
。Ruby的正则表达式引擎也很快,所以在使用大型正则表达式模式时不会受到影响。谢谢,你的方法非常好。在我的实际代码中,关键字来自一些额外的配置,这里我只想知道哪个解决方案更好。这就是我的想法。通过只计算一次联合关键字并将结果regexp存储在方法外部(例如属性中),可以节省更多时间。那么您的整个方法定义就是!!(src=~@keywords)
。Ruby的正则表达式引擎也很快,所以在使用大型正则表达式模式时不会受到影响。