当我尝试在 case 语句中匹配字符串 '3' 时,它匹配范围是否达到 '9',而不是 '10'。
我猜它与三重等号运算符有关,但我不知道它可以在范围内但不匹配的确切原因。
这是一个 IRB 运行,记录了有效(使用“9”)和不起作用(使用“10”)的两种情况:
case '3'
when ('0'...'9')
puts "number is valid"
else
puts "number is not valid"
end
Run Code Online (Sandbox Code Playgroud)
输出: number is valid
case '3'
when ('0'...'9')
puts "number is valid"
else
puts "number is not valid"
end
Run Code Online (Sandbox Code Playgroud)
输出: number is not valid
我用作预期结果参考的方法是
Enumerable#include?
Enumerable#member?
,查看转换为数组时输出的内容是 ( Enumerable#to_a)。
“大小写相等” ( ===) 运算符的结果让我感到惊讶。
case '3'
when ('0'...'10')
puts "number is valid"
else
puts "number is not valid"
end
Run Code Online (Sandbox Code Playgroud)
3li*_*t0r 42
范围cover?用于大小写相等。所以它正在比较'3' >= '0' && '3' < '10'哪个结果false因为'3' < '10' #=> false。字符串基于字符值进行比较。
为了更好地理解,您可能希望将字符串视为字符数组:
['3'] <=> ['1', '0'] #=> 1 (first operand is larger than the second)
Run Code Online (Sandbox Code Playgroud)
要解决此问题,请将case输入转换为整数并使用整数范围:
case 3 # or variable.to_i
when 0...10
puts 'number is valid'
else
puts 'number is invalid'
end
Run Code Online (Sandbox Code Playgroud)
这是有效的,因为整数不是基于字符代码进行比较,而是基于实际值。3 >= 0 && 3 < 10结果在true.
或者,您可以通过不传递范围而是传递一个方法来明确告诉何时使用member?(or include?) 方法。
case '3'
when ('0'...'10').method(:member?)
puts 'number is valid'
else
puts 'number is invalid'
end
Run Code Online (Sandbox Code Playgroud)
Sil*_*olo 17
begin <= obj < end
Run Code Online (Sandbox Code Playgroud)
所以,在你的情况下,我们得到
'0' <= '3' < '10'
Run Code Online (Sandbox Code Playgroud)
并且<=和<使用字典顺序比较字符串,所以比较是错误的。
另一方面,我们必须做更多的挖掘才能弄清楚member?/include?实际做什么(两者是等价的)。如果我们查看源代码,我们会看到两者都调用了一个被调用的函数range_include_internal,该函数对字符串参数有一个特殊情况,其行为与cover?. 后者调用rb_str_include_range_p具有更多特殊情况,包括您的数字情况。