我有一个来自输入表单的字符串,并希望使用不区分大小写的比较将其与许多可能的验证字符串进行比较,如果找到匹配则返回true
。
例如,如果输入为input = 'florida'
(或'FL'
或'flor.'
)并将其与validate = ['fl', 'florida']
或某些此类验证数组进行比较,则应返回true
。
我知道我可以使用标记select
和明确的选项列表,但是,这更像是一个例子。在我的情况下,该字段可以返回多种类型的字符串,所以我试图找到一个“解析”的好解决方案。好像Ruby擅长的那种问题?
答案 0 :(得分:2)
比较多个字符串的最快方法是使用正则表达式,尤其是当您可以对它们进行变换时。 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
是假值,而其他每个结果都被认为是真的。强制使用true / 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.'
与\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(使用|
)。
答案 1 :(得分:1)
我通常只是将值放入数组然后使用include?方法,如果输入匹配数组的任何元素,则返回true。
['fl', 'florida', 'FL'].include?(input)