【问题标题】:Shorter ways to write this condition n != 1 && n != 2 && n != 3 && n !=4 in Ruby在 Ruby 中编写此条件 n != 1 && n != 2 && n != 3 && n !=4 的更短方法
【发布时间】:2017-04-13 21:05:42
【问题描述】:

我想检查输入是否是 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

【问题讨论】:

  • [1,2,3,4].include?(n)
  • n != 1 || n != 2 || n != 3 || n != 4 始终为真。你是说n != 1 && n != 2 && n != 3 && n != 4 吗?
  • 对不起,我才意识到这一点。已编辑。
  • 这里不需要chomp
  • 这四个数字可能是12354321,还是他们总是构成一个范围?如果它们不需要代表范围,您应该使用不同的示例。

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


【解决方案1】:

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

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

【讨论】:

  • 不知道cover?。因此,在这种情况下,cover? 正在执行n >= 1 && n <= 4 而不是检查Range 中的每个项目。
  • 没错。这使得更大范围的速度更快,但可能会导致字符串范围的意外结果。
  • Range#include?Range#cover? 相同,此时端点是数字。
【解决方案2】:

最快的检查:

if n < 1 || n > 4

【讨论】:

  • 你的意思可能是n &lt; 1
  • 是的,对于某些人来说,它可能更容易看到!(n >= 1 && n
【解决方案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

或者有点干燥:

[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 将交替成为最快和次快,然后在ttm 中使用case

结果会随着更多值的添加而改变。特别是,我认为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

【讨论】:

  • 严格来说我们不应该在 Ruby 中说 case expression 而不是 case statement 吗?
【解决方案4】:

我会为此使用Range,并使用unless-statement 而不是if

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

【讨论】:

    【解决方案5】:

    如果你的范围是联合的,你可以使用

    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)
    

    【讨论】:

    • 我同意这很有趣和令人惊讶。为什么case表达式这么快?本身会提出一个有趣的问题......
    • 我想这是因为第一个是在正 n 时评估的 2 个表达式,而其他是具有自己开销的方法。可以使用分析器进行检查。
    • 看看n = 1n = 4 是否对case 语句有影响会很有趣。
    • 在 W7 下使用 MRI 2.3.0 64bit 的另一台电脑上进行了测试,差异非常小(n=1 稍快),在这个版本中,第一个和最后一个解决方案竞争最快,大多数时候它是第一个,它证实了我已经知道的,总是在你将要在生产中使用的系统上运行你的基准测试
    【解决方案6】:

    您可以在数组中定义包含元素,并使用include? 检查n 是否是其中的任何一个:

    [1, 2, 3, 4].include?(n)
    

    【讨论】:

      【解决方案7】:

      其他帖子中的答案在文中回答了您的问题,但这是我对标题中您问题的回答:

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-29
        • 1970-01-01
        • 2012-07-30
        • 2015-10-08
        • 1970-01-01
        • 1970-01-01
        • 2013-06-19
        • 1970-01-01
        相关资源
        最近更新 更多