我是编程初学者,但对以下if
语句有疑问:
if (f.year == (10 || 20 || 30 || 40 || 50 || 60 || 70 || 80 || 90 || 100 || 110 || 120)) && (f.rund != true)
第一个问题是这段代码非常复杂。其实我只想检查是否f.year
是一个圆形的两位数。
接下来我的代码无法正常工作。不知何故,它只选择了f.year
equal 10
。
我该如何解决这些问题?
我是编程初学者,但对以下if
语句有疑问:
if (f.year == (10 || 20 || 30 || 40 || 50 || 60 || 70 || 80 || 90 || 100 || 110 || 120)) && (f.rund != true)
第一个问题是这段代码非常复杂。其实我只想检查是否f.year
是一个圆形的两位数。
接下来我的代码无法正常工作。不知何故,它只选择了f.year
equal 10
。
我该如何解决这些问题?
这是因为
(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
您可以使用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
要回答您的第一点,代码应为:
if (f.year == 10 || f.year == 20 || f.year == 30 ...
您的表达式f.year == (10 || 20 || 30 ...
不起作用,因为它由 ruby 评估如下:
10 || 20 || 30 ...
首先被评估||
左操作数,否则返回其右操作数nil
或false
为“真”的东西,所以表达式10 || 20 || 30 ...
计算为10
(f.year == 10) && (f.rund != true)
您已经被告知为什么您的代码不能按预期工作,我回答只是建议在这里使用数学方法而不是 using 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
我不确定你的问题,但第一个条件可以写成
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)
很难说 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
条件不能以这种方式工作。在检查与 的相等性之前,对括号内的所有数字OR
进行评估,与 连接。f.year
这里的大多数答案似乎过于复杂。您可以使用基本数学来解决您的问题:
if year % 10 == 0 && year.to_s.size == 2
# do stuff
end
在此示例中,模运算符%
在除以时返回余数。10
如果余数为 0,则为 10 的倍数。您可以使用任何数字。模 2 将检查数字是否为偶数。
第二部分检查位数。它首先将其转换为字符串to_s
,然后检查它的长度,基本上是那里有多少个字符。将 10 转换为'10'
包含 2 个字符的字符串。
你的问题似乎有点不清楚。您想在代码示例中包含数字 100、110 和 120 吗?还是您只想要文本中所述的两位数字?