写这个条件的方法更短n!= 1&& n!= 2&& n!= 3&&在Ruby中n!= 4

时间:2017-04-13 21:05:42

标签: ruby algorithm if-statement operators conditional-statements

我想检查输入是否是四个数字1,2,3,4中的一个。如果不是,则应该有错误消息。我从这开始

n = gets.chomp.to_i
if n != 1 && n != 2 && n != 3 && n != 4
    puts 'invalid input'
end

在其他语言中也会发生很多这种情况。如何缩短上述条件n != 1 && n != 2 && n != 3 && n != 4

7 个答案:

答案 0 :(得分:8)

我会使用可能Range#cover?faster than include?

number = gets.chomp.to_i
puts('invalid input') unless (1..4).cover?(number)

答案 1 :(得分:5)

最快的检查:

if n < 1 || n > 4

答案 2 :(得分:3)

嗯,有case声明:

case num
when 1,2,3,4
  puts "it's ok"
else
  puts "it's not ok"
end

例如:

[0, 1, 4, 5].each do |num|
  case num
  when 1,2,3,4
    puts "#{num} is ok"
  else
    puts "#{num} is not ok"
  end
end

# >> 0 is not ok
# >> 1 is ok
# >> 4 is ok
# >> 5 is not ok

或者有点DRYer:

[0, 1, 4, 5].each do |num|
  puts case num
       when 1,2,3,4
         "#{num} is ok"
       else
         "#{num} is not ok"
       end
end

# >> 0 is not ok
# >> 1 is ok
# >> 4 is ok
# >> 5 is not ok

而且,由于when允许范围,因此您可以使用when 1 .. 4

虽然我很欣赏基准测试结果显示使用case的速度最快,但没有任何意义,因为Casper应该是这样的。这是我发现的:

require 'fruity'

n = 1
compare do
  casper1 { n < 1 || n > 4 }
  casper2 { n >= 1 && n <= 4 }
  casper3 { 1 <= n && n <= 4 }
  sagarpandya82 {n.between?(1,4)}
  spickerman {(1..4).cover?(n)}
  reitermarkus {[1, 2, 3, 4].include?(n)}
  ttm {case n;when 1,2,3,4;true;else;false;end}
end

# >> Running each test 262144 times. Test will take about 11 seconds.
# >> casper2 is similar to casper3
# >> casper3 is faster than ttm by 2x ± 1.0
# >> ttm is faster than casper1 by 2x ± 1.0 (results differ: true vs false)
# >> casper1 is faster than sagarpandya82 by 3x ± 1.0 (results differ: false vs true)
# >> sagarpandya82 is similar to spickerman
# >> spickerman is faster than reitermarkus by 2x ± 0.1

在多次运行时,casper2casper3将以最快和最快的速度交替,然后在case中使用ttm

随着更多值的添加,结果会发生变化。特别是,我认为includewhen 1,2,3,4测试会受到严重影响。

只是为了表明没有必要折叠空间,或者换句话说,空白没有区别:

require 'fruity'

n = 1
compare do
  ttm1 {case n;when 1,2,3,4;true;else;false;end}
  ttm2 {case n; when 1,2,3,4; true; else; false; end}
  ttm3 {
    case n
        when 1,2,3,4
          true
        else
          false
        end
  }
end

# >> Running each test 131072 times. Test will take about 2 seconds.
# >> ttm1 is similar to ttm3
# >> ttm3 is similar to ttm2

有了Fruity,当你看到这些“类似于”的结果时,它们往往会按顺序交替,因为速度的差异通常是系统在测试过程中摆动的结果。

最后,将when 1,2,3,4when 1..4进行比较:

require 'fruity'

n = 1
compare do
  ttm1 {
    case n
    when 1,2,3,4
      true
    else
      false
    end
  }

  ttm2 {
    case n
    when 1..4
      true
    else
      false
    end
  }
end

# >> Running each test 131072 times. Test will take about 2 seconds.
# >> ttm1 is faster than ttm2 by 8x ± 10.0

答案 3 :(得分:2)

我会使用Rangeunless - 语句而不是if

unless (1..4).include?(n)
  puts 'invalid input'
end

答案 4 :(得分:2)

如果你的范围是关节,你可以使用

n.between?(1,4)

我对最快的解决方案感到好奇,令我惊讶的是case解决方案,无论是在范围内外的n,还是在Windows 7下至少在MRI 1.9.3上。只有坑,它也是最长的解决方案..

Benchmark.bm do |x|
  x.report {r.times {n < 1 || n > 4}}
  x.report {r.times {n.between?(1,4)}}
  x.report {r.times {(1..4).cover?(n)}}
  x.report {r.times {[1, 2, 3, 4].include?(n)}}
  x.report {r.times {case n;when 1,2,3,4;true;else;false;end}}
end

给出

       user     system      total        real
   0.093000   0.000000   0.093000 (  0.093600)
   0.141000   0.000000   0.141000 (  0.140400)
   0.140000   0.000000   0.140000 (  0.140400)
   0.265000   0.000000   0.265000 (  0.265200)
   0.063000   0.000000   0.063000 (  0.062400)

答案 5 :(得分:1)

您可以在数组中定义包含元素,并使用n检查include?是否为[1, 2, 3, 4].include?(n)

{{1}}

答案 6 :(得分:0)

其他帖子中的答案会在文字中回答您的问题,但以下是我在标题中对您的问题的回答:

  

编写此条件的更短方法n!= 1 || n!= 2 || n!= 3 ||在Ruby中n!= 4    n!= 1 || n!= 2 || n!= 3 ||在Ruby中n!= 4

表达式:true总是等同于此。如果你想把它放在一个条件下,概念上最简单的就是不要使用任何条件。没有条件,只需在这种条件下写下你想做的事情。