比较多个字符串的最快方法是使用正则表达式,尤其是当您可以对它们进行变体时。Ruby 有一些帮助方法可以使这更容易:
validate = ['fl', 'florida']
regex = /\b(?:#{ Regexp.union(validate.sort_by{ |s| [-s.size, s] }).source })\b/i
regex # => /\b(?:florida|fl)\b/i
'FL'[regex] # => "FL"
'florida'[regex] # => "florida"
'flor.'[regex] # => nil
请记住,在 Ruby 中,只有nil
和false
是假值,其他所有结果都被认为是真的。强制真/假值的捷径是使用!!
( not not
)。将上述结果与以下结果进行比较:
!!'FL'[regex] # => true
!!'florida'[regex] # => true
!!'flor.'[regex] # => false
'flor.'
不匹配,因为模式正在寻找全字匹配,由于周围的\b
(字边界)标记。删除它们,或者添加flor.
到模式中可以解决这个问题:
validate = ['fl', 'florida', 'flor']
regex = /\b(?:#{ Regexp.union(validate.sort_by{ |s| [-s.size, s] }).source })\b/i
'flor.'[regex] # => "flor"
'flor.'
不能使用,因为which\b
与尾随.
. flor.
删除\b
:
validate = ['fl', 'florida', 'flor.']
regex = /(?:#{ Regexp.union(validate.sort_by{ |s| [-s.size, s] }).source })/i
'flor.'[regex] # => "flor."
validate
将数组中的值传递给时,您可以非常富有表现力,Regexp.union
但要注意union
转义字符串的内容以保护正则表达式中的特殊字符:
Regexp.union(%w[a \b dollars$ . * ? +]) # => /a|\\b|dollars\$|\.|\*|\?|\+/
你可以控制这个:
patterns = %w[a \b dollars$ . \* \? \+]
/#{ patterns.join('|') }/ # => /a|\b|dollars$|.|\*|\?|\+/
有时我分几个步骤构建一个模式,有时我可以一次完成。这是你必须尝试的东西。
回到开头。联合模式更快的原因是正则表达式引擎非常快,并且字符串只搜索一次,即使模式中的多个元素是 OR'd(使用|
)。