【发布时间】:2017-05-12 04:09:03
【问题描述】:
有没有办法通过字符串操作来创建条件。这是我尝试将字符串作为条件传递给 include? 方法的代码。
"hello eveyone in the house".include?(%w('hello' 'world' 'new\ york' 'place').join(" || ").to_s)
【问题讨论】:
标签: ruby-on-rails ruby conditional whitelist
有没有办法通过字符串操作来创建条件。这是我尝试将字符串作为条件传递给 include? 方法的代码。
"hello eveyone in the house".include?(%w('hello' 'world' 'new\ york' 'place').join(" || ").to_s)
【问题讨论】:
标签: ruby-on-rails ruby conditional whitelist
include? 的条件参数是不可能的,因为include? 只接受字符串参数。
但是你可以这样写:
['hello', 'world', 'new york', 'place'].any? { |word|
"hello everyone in the house".include?(word)
}
或者你可以从你的字符串生成一个正则表达式:
"hello eveyone in the house".match?(
/#{['hello', 'world', 'new york', 'place'].join('|')}/
)
【讨论】:
match? 最近在 Ruby 2.4 中被引入。如果您使用的是旧版本,请改用match。
any? 的优点还在于它会在找到字符串后立即停止。
另一种可能性是 split 单词并使用 set intersection :
sentence = "hello everyone in the house"
whitelist = %w(hello world new-york place)
found_words = sentence.split & whitelist
p found_words # => ["hello"]
p found_words.empty? # => false
警告:仅当白名单不包含任何包含多个单词的字符串时才有效。例如new york 在原始问题中。
有关更强大的解决方案,请参阅@spickermann 的回答。
【讨论】:
new york)。因为在句子中new york 将被拆分为['new', 'york'] 并且不与数组[new york] 相交。
做了一些基准测试来测试速度,令我惊讶的是,spickerman 的第一个解决方案是迄今为止在 windows 盒子上的 MRI Ruby 2.3.0 中最快的,其次是交集,而我自己的 Regexp.union 解决方案最后: (
require 'benchmark'
s = "hello everyone in the house"
a = ['hello', 'world', 'new york', 'place']
N = 10_000
Benchmark.bmbm do |x|
x.report("Union ") { N.times { s.match(Regexp.union(a)) }}
x.report("Union and scan") { N.times { s.scan(Regexp.union(a)) }}
x.report("Interpollation") { N.times { s.match(/#{a.join('|')}/)}}
x.report("intersect ") { N.times { s.split & a }}
x.report("block ") { N.times { a.any? { |word| s.include?(word)}}}
end
Rehearsal --------------------------------------------------
Union 0.110000 0.000000 0.110000 ( 0.116051)
Union and scan 0.124000 0.000000 0.124000 ( 0.121038)
Interpollation 0.110000 0.000000 0.110000 ( 0.105943)
intersect 0.015000 0.000000 0.015000 ( 0.018456)
block 0.000000 0.000000 0.000000 ( 0.001908)
----------------------------------------- total: 0.359000sec
user system total real
Union 0.109000 0.000000 0.109000 ( 0.111704)
Union and scan 0.125000 0.000000 0.125000 ( 0.119122)
Interpollation 0.109000 0.000000 0.109000 ( 0.105288)
intersect 0.016000 0.000000 0.016000 ( 0.017283)
block 0.000000 0.000000 0.000000 ( 0.001764)
【讨论】:
a 的末尾,看看这对结果有何影响。事实上,@spickerman 的方法在处理完“hello”后退出,而其他方法继续运行。
N正则表达式,将Regexp.union移出循环,它可能是最快的。