在没有 Regexp 的情况下测试可剥离的空白
您可以使用String#strip! 的一个小技巧,如果找不到要删除的空格,它会返回nil。例如:
# return true if str has leading/trailing whitespace;
# otherwise returns false
def strippable? str
{ str => !!str.dup.strip! }
end
# leading space, trailing space, no space
test_values = [ ' foo', 'foo ', 'foo' ]
test_values.map { |str| strippable? str }
#=> [{" foo"=>true}, {"foo "=>true}, {"foo"=>false}]
这不依赖于正则表达式,而是依赖于字符串的属性和倒置#strip! 的布尔结果。不管 Ruby 引擎是否在后台使用正则表达式,这些类型的 String 方法通常比可比较的 Regexp 匹配更快,但您的里程和具体用例可能会有所不同。
正则表达式的替代方案
使用与上面相同的测试数据,您可以使用正则表达式执行类似的操作。例如:
# leading space, trailing space, no space
test_values = [ ' foo', 'foo ', 'foo' ]
# test start/end of string
test_values = [ ' foo', 'foo ', 'foo' ].grep /\A\s+|\s+\z/
#=> [" foo", "foo "]
# test start/end of line
test_values = [ ' foo', 'foo ', 'foo' ].grep /^\s+|\s+$/
#=> [" foo", "foo "]
基准
require 'benchmark'
ITERATIONS = 1_000_000
TEST_VALUES = [ ' foo', 'foo ', 'foo' ]
def regex_grep array
array.grep /^\s+|\s+$/
end
def string_strip array
array.map { |str| { str => !!str.dup.strip! } }
end
Benchmark.bmbm do |x|
n = ITERATIONS
x.report('regex') { n.times { regexp_grep TEST_VALUES } }
x.report('strip') { n.times { string_strip TEST_VALUES } }
end
user system total real
regex 1.539269 0.001325 1.540594 ( 1.541438)
strip 1.256836 0.001357 1.258193 ( 1.259955)
100 万次迭代中的四分之一秒可能看起来差别不大,但在大得多的数据集或迭代中,它可以加起来。是否足以关心这个特定的用例取决于你,但一般模式是原生 String 方法(不管它们是如何由引擎盖下的解释器实现的)通常比正则表达式模式匹配更快。当然也有边缘情况,但这就是基准测试的目的!