【问题标题】:Determining if a variable is within range?确定变量是否在范围内?
【发布时间】:2010-10-26 14:39:54
【问题描述】:

我需要编写一个循环来执行以下操作:

if i (1..10)
  do thing 1
elsif i (11..20)
  do thing 2
elsif i (21..30)
  do thing 3
etc...

但到目前为止,在语法方面走错了路。

【问题讨论】:

    标签: ruby integer conditional range


    【解决方案1】:

    如果您需要最快的方法,请使用旧的比较。

    require 'benchmark'
    
    i = 5
    puts Benchmark.measure { 10000000.times {(1..10).include?(i)} }
    puts Benchmark.measure { 10000000.times {i.between?(1, 10)}   }
    puts Benchmark.measure { 10000000.times {1 <= i && i <= 10}   }
    

    在我的系统上打印:

    0.959171   0.000728   0.959899 (  0.960447)
    0.919812   0.001003   0.920815 (  0.921089)
    0.340307   0.000000   0.340307 (  0.340358)
    

    如您所见,双重比较比#include?#between? 方法快几乎快3倍

    【讨论】:

      【解决方案2】:

      您可以使用
      if (1..10).cover? i then thing_1 elsif (11..20).cover? i then thing_2

      根据Fast Ruby 中的这个基准,它比include?

      【讨论】:

      • 这个其实快很多
      【解决方案3】:

      不是问题的直接答案,但如果您想要与“内部”相反:

      (2..5).exclude?(7)
      

      是的

      【讨论】:

      【解决方案4】:

      您通常可以通过以下方式获得更好的性能:

      if i >= 21
        # do thing 3
      elsif i >= 11
        # do thing 2
      elsif i >= 1
        # do thing 1
      

      【讨论】:

        【解决方案5】:

        对于字符串:

        (["GRACE", "WEEKLY", "DAILY5"]).include?("GRACE")
        

        #=>真

        【讨论】:

          【解决方案6】:
          如果 i.between?(1, 10) 做一件事 elsif i.between?(11,20) 做事2 ...

          【讨论】:

          • 这也适用于 DateDateTime 对象,而 === 不适用。
          • i.between?(1..10) 不行(如果是..)我想一定是有原因的
          • between? 需要两个不允许范围的参数。
          • 是包容还是独占?
          • @andrewcockerham 包容性。 3.between?(1, 3) =&gt; true
          【解决方案7】:

          更动态的答案,可以用 Ruby 构建:

          def select_f_from(collection, point) 
            collection.each do |cutoff, f|
              if point <= cutoff
                return f
              end
            end
            return nil
          end
          
          def foo(x)
            collection = [ [ 0, nil ],
                           [ 10, lambda { puts "doing thing 1"} ],
                           [ 20, lambda { puts "doing thing 2"} ],
                           [ 30, lambda { puts "doing thing 3"} ],
                           [ 40, nil ] ]
          
            f = select_f_from(collection, x)
            f.call if f
          end
          

          因此,在这种情况下,“范围”实际上只是用 nil 围起来以捕捉边界条件。

          【讨论】:

            【解决方案8】:

            使用=== 运算符(或其同义词include?

            if (1..10) === i
            

            【讨论】:

            • i 一起工作的好处不是数字(如nil
            • 如果范围非常大,这似乎不是一个非常有效的解决方案。
            • 对于未来的读者,if i === (1..10) 的替代方式将不起作用
            • @rthbound,为什么? (1..10000000000000000) 不是数组。 (1..10000000000000000) === 5000000000000000 只是在后台进行“介于”测试
            • @Anwar 你能解释一下为什么它不能以另一种方式工作吗?
            【解决方案9】:

            正如@Baldu 所说,使用 === 运算符或用例/当内部使用 === 时:

            case i
            when 1..10
              # do thing 1
            when 11..20
              # do thing 2
            when 21..30
              # do thing 3
            etc...
            

            【讨论】:

            • 在所有答案中,当您有多个范围时,这也可能是最高效的。
            【解决方案10】:

            如果您仍想使用范围...

            def foo(x)
             if (1..10).include?(x)
               puts "1 to 10"
             elsif (11..20).include?(x)
               puts "11 to 20"
             end
            end
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2011-12-19
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多