2011-12-29 35 views
1

我想查看一个字符串是否包含关键字列表中的关键字。如何查看一个字符串是否包含关键字列表中的关键字?

我有以下功能:

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 

但如果关键字数组列表很长,这种做法是不那么有效。

回答

1

我很好奇什么是最快的解决方案,我创建了迄今为止所有答案的基准。

我修改了steenslag answer了一下。出于调整的原因,我只为每个测试创建一次正则表达式。

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) 

该解决方案使用正则表达式是最快的,如果你创建的正则表达式一次。

+0

非常感谢。 – donnior 2011-12-30 04:14:52

3

看起来像一个很好的用例Enumerable#any?方法:

def needfilter?(src) 
    ["keyowrd_1","keyowrd_2","keyowrd_3","keyowrd_4","keyowrd_5"].any? do |kw| 
    src.include? kw 
    end 
end 
+0

omg,我开启了'任何?'功能,谢谢。 – donnior 2011-12-29 14:20:29

0

我认为,当你想到

def need_filter?(src) 
    (src.split(/ /) & ["keyowrd_1","keyowrd_2","keyowrd_3","keyowrd_4","keyowrd_5"]).empty? 
end 

就可以了(因为它在Array include any value from another array?定律描述),并会比any?更快include?

+0

根据问题,src是一个字符串。 – steenslag 2011-12-29 14:07:06

+0

我已经通过将所有字符串拆分为单词来修复它。 – Hauleth 2011-12-29 14:14:24

+0

谢谢,但这种方法失败了,src字符串可能非常复杂。而且我认为效率不高,因为我只想知道该字符串是否触及任何关键字,如果是这样,请忽略其他关键字,只是返回true – donnior 2011-12-29 14:18:28

1
def need_filter?(src) 
    !!(src =~ /keyowrd_1|keyowrd_2|keyowrd_3|keyowrd_4|keyowrd_5/) 
end 

=~方法返回一个fixnum或nil。双重轰炸将其转换为布尔值。

+0

谢谢,但关键字列表可能非常大。 – donnior 2011-12-29 14:11:47

+0

你也可以用'/#{keywords.join('|')} /'来构建正则表达式(假设关键字不包含符号)。这可能是最快的解决方案。但尝试基准所有答案。 – 2011-12-29 14:23:13

+0

谢谢,现在工作得很好。 – donnior 2011-12-29 14:35:23

1

这是我做的方式:

def needfilter?(src) 
    keywords = Regexp.union("keyowrd_1","keyowrd_2","keyowrd_3","keyowrd_4","keyowrd_5") 
    !!(src =~ keywords) 
end 

该解决方案有:

  • 没有迭代使用Regexp.union

  • 单正则表达式应该是快速即使是一大组关键字。请注意,对方法中的关键字进行硬编码并不理想,但我假设这只是为了举例。

  • +0

    谢谢,你的方法非常好。在我的真实代码中,关键字来自一些额外的配置,这里我只想知道哪种解决方案更好。 – donnior 2011-12-30 04:23:08

    +0

    这就是我的想法。您可以通过精确计算联合关键字一次并将生成的正则表达式存储在方法外,例如属性中,节省更多时间。那么你的整个方法定义就是'!!(src =〜@keywords)'。 – 2011-12-30 14:31:15

    +0

    Ruby的正则表达式引擎速度也很快,因此在使用大型正则表达式模式时不会受到影响。 – 2011-12-31 20:11:20

    相关问题