2

我是编程初学者,但对以下if语句有疑问:

if (f.year == (10 || 20 || 30 || 40 || 50 || 60 || 70 || 80 || 90 || 100 || 110 || 120)) && (f.rund != true)

第一个问题是这段代码非常复杂。其实我只想检查是否f.year是一个圆形的两位数。

接下来我的代码无法正常工作。不知何故,它只选择了f.yearequal 10

我该如何解决这些问题?

4

7 回答 7

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
于 2013-09-20T08:02:04.037 回答
4

您可以使用Range#stepNumeric#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]

并致电Enumerable#include?

(10..120).step(10).include? year

10.step(120, 10).include? year
于 2013-09-20T08:42:06.010 回答
2

要回答您的第一点,代码应为:

if (f.year == 10 || f.year == 20 || f.year == 30 ...

您的表达式f.year == (10 || 20 || 30 ...不起作用,因为它由 ruby​​ 评估如下:

  • 括号力10 || 20 || 30 ...首先被评估
  • 如果为真,则运算符返回其||左操作数,否则返回其右操作数
  • Ruby 认为任何不是nilfalse为“真”的东西,所以表达式10 || 20 || 30 ...计算为10
  • 所以你的表达归结为(f.year == 10) && (f.rund != true)
于 2013-09-20T08:00:26.607 回答
2

您已经被告知为什么您的代码不能按预期工作,我回答只是建议在这里使用数学方法而不是 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
于 2013-09-20T09:05:45.997 回答
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)
于 2013-09-20T08:02:08.127 回答
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
于 2013-09-20T16:55:41.120 回答
0

条件不能以这种方式工作。在检查与 的相等性之前,对括号内的所有数字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 吗?还是您只想要文本中所述的两位数字?

于 2013-09-20T08:15:19.813 回答