我是编程的初学者,并且遇到了这个if
语句的问题:
if (f.year == (10 || 20 || 30 || 40 || 50 || 60 || 70 || 80 || 90 || 100 || 110 || 120)) && (f.rund != true)
第一个问题是这段代码非常复杂。实际上我只想检查f.year
是否是一个两位数的圆形数字。
接下来我的代码无法正常运行。不知何故,它只选择等于f.year
的{{1}}。
我该如何解决这些问题?
答案 0 :(得分:4)
这是因为
(10 || 20 || 30 || 40 || 50 || 60 || 70 || 80 || 90 || 100 || 110 || 120)
表达式始终计算为10
。
您可以使用例如:
解决问题(1..12).map { |el| el * 10 }.include?(f.year)
或者,正如@AurpRakshit所建议的那样:
(1..12).map(&10.method(:*)).include?(f.year)
Here你有更多生成这种数组的例子。
或者,如果您真的想检查f.year
是否为两位数字,您可以:
(10...100).include?(f.year) && f.year % 1 == 0
答案 1 :(得分:4)
您可以使用Range#step
或Numeric#step
:
(10..120).step(10).to_a #=> [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120]
10.step(120, 10).to_a #=> [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120]
(10..120).step(10).include? year
10.step(120, 10).include? year
答案 2 :(得分:2)
要回答您的第一点,代码应为:
if (f.year == 10 || f.year == 20 || f.year == 30 ...
您的表达式f.year == (10 || 20 || 30 ...
不起作用,因为它由ruby评估如下:
10 || 20 || 30 ...
首先评估||
运算符返回其左操作数(如果为true),否则返回其右操作数nil
或false
的任何内容视为“true”,因此表达式10 || 20 || 30 ...
的计算结果为10
(f.year == 10) && (f.rund != true)
答案 3 :(得分:2)
您已经被告知为什么您的代码无法正常工作,我只是建议在这里使用数学方法而不是使用include?
,您的条件可以写成:
if f.year.modulo(10).zero? && f.year.between?(10, 120) && !f.rund
...
它可能稍微不那么清楚但速度要快得多。
更新
此解决方案的缺点是当f.year
不是Numeric
对象时失败:
nil.modulo(10)
# NoMethodError: ...
虽然:
[10].include?(nil)
# => false
基准测试:
require 'fruity'
a = (1..10000)
compare do
map_include do
a.each do |i|
(1..12).map(&10.method(:*)).include?(i)
end
end
step_include do
a.each do |i|
(10..120).step(10).include?(i)
end
end
divmod_include do
a.each do |i|
q, r = i.divmod(10); (1..12).include?(q) && r.zero?
end
end
math do
a.each do |i|
i.modulo(10).zero? && i.between?(10, 120)
end
end
end
Running each test once. Test will take about 2 seconds.
math is faster than divmod_include by 1.9x ± 0.01
divmod_include is faster than step_include by 9x ± 0.1
step_include is faster than map_include by 3.4x ± 0.1
答案 4 :(得分:1)
我不确定你的问题,但第一个条件可以写成
q, r = f.year.divmod(10); (1..12).include?(q) && r.zero?
或
[10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120].include?(f.year)
答案 5 :(得分:1)
很难说OP想要什么,但......
require 'fruity'
ARY = (1..1000).to_a
compare do
test_mod_and_le do
ARY.each do |i|
(i % 10 == 0) && (i <= 120)
end
end
test_mod_and_range do
ARY.each do |i|
(i % 10 == 0) && ((10..120) === i)
end
end
test_case_when do
ARY.each do |i|
case i
when 10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120
true
else
false
end
end
end
map_include do
ARY.each do |i|
(1..12).map(&10.method(:*)).include?(i)
end
end
step_include do
ARY.each do |i|
(10..120).step(10).include?(i)
end
end
divmod_include do
ARY.each do |i|
q, r = i.divmod(10); (1..12).include?(q) && r.zero?
end
end
math do
ARY.each do |i|
i.modulo(10).zero? && i.between?(10, 120)
end
end
end
哪个输出:
Running each test 32 times. Test will take about 4 seconds.
test_case_when is similar to test_mod_and_le
test_mod_and_le is faster than test_mod_and_range by 19.999999999999996% ± 10.0%
test_mod_and_range is faster than math by 50.0% ± 10.0%
math is faster than divmod_include by 80.0% ± 10.0%
divmod_include is faster than step_include by 5.9x ± 0.1
step_include is faster than map_include by 2.9x ± 0.1
答案 6 :(得分:0)
条件不起作用。括号内与OR
相关联的所有数字都会在检查与f.year
的相等性之前进行评估。
这里的大多数答案似乎过于复杂。您可以使用基本数学来解决您的问题:
if year % 10 == 0 && year.to_s.size == 2
# do stuff
end
在此示例中,模运算符%
在除以10
时返回余数。如果余数为0,则它是10的倍数。您可以使用任何数字。 Modulo 2会检查数字是否均匀。
第二部分检查位数。它首先使用to_s
将其转换为字符串,然后检查它的长度,基本上是多少个字符。将10转换为字符串会产生'10'
,其中包含2个字符。
您的问题似乎有点不清楚。您想要在代码示例中包含数字100,110和120吗?或者您只想要两个数字,如文中所述?