【问题标题】:Checking if a variable is not nil and not zero in ruby检查变量是否在 ruby​​ 中不为零且不为零
【发布时间】:2010-09-20 02:44:03
【问题描述】:

我正在使用以下代码来检查变量是否不为零且不为零

if(discount != nil && discount != 0) 
  ...
end

有没有更好的方法来做到这一点?

【问题讨论】:

标签: ruby


【解决方案1】:

是的,我们在 ruby​​ 中确实有一个干净的方法。

discount.to_f.zero?

此检查处理大量情况,即折扣可能为零,折扣可能是 int 0,折扣可能是浮动 0.0,折扣可能是字符串“0.0”、“0”。

【讨论】:

    【解决方案2】:

    我更喜欢使用更简洁的方法:

    val.to_i.zero?
    
    如果 val 是 nil,

    val.to_i 将返回 0,

    之后,我们需要做的就是检查最终值是否为零。

    【讨论】:

      【解决方案3】:

      好的,5年过去了......

      if discount.try :nonzero?
        ...
      end
      

      请务必注意,try 是在 ActiveSupport gem 中定义的,因此它在普通 ruby​​ 中不可用。

      【讨论】:

      • 请注意,这是一个 rails-specific 答案。 Vanilla ruby​​ 没有try 方法。
      • 正确。虽然它更像是特定于 ActiveSupport 的,但它比完整的 rails 更轻且使用广泛。无论如何,现在@ndn 的回应是正确的。
      • 编辑为使用安全导航
      • 答案现在重复了stackoverflow.com/a/34819818/1954610 ...我认为将其保留为try 以显示替代选项是有价值的(这就是为什么它首先被赞成!),所以只要读者清楚ActiveSupport 不是香草红宝石。
      • 取点,回滚回答。
      【解决方案4】:

      替代解决方案是使用 Refinements,如下所示:

      module Nothingness
        refine Numeric do
          alias_method :nothing?, :zero?
        end
      
        refine NilClass do
          alias_method :nothing?, :nil?
        end
      end
      
      using Nothingness
      
      if discount.nothing?
        # do something
      end
      

      【讨论】:

        【解决方案5】:
        if discount.nil? || discount == 0
          [do something]
        end
        

        【讨论】:

          【解决方案6】:
          def is_nil_and_zero(data)
               data.blank? || data == 0 
          end  
          

          如果我们传递 "" 它将返回 false 而空白?返回真。 当 data = false 时也是如此 空白的?对于 nil、false、空或空白字符串返回 true。 所以最好使用空白?避免空字符串的方法。

          【讨论】:

          • blank? 是特定于 rails 的方法,在 vanilla ruby​​ 中不可用。
          • 你是对的!!我认为这与此处发布的“ror”标签有关。我的错。这在香草红宝石中是行不通的。
          • 我将这个方法命名为blank_or_zero?
          【解决方案7】:

          从 Ruby 2.3.0 开始,您可以将安全导航运算符 (&.) 与 Numeric#nonzero? 结合使用。 &. 返回 nil 如果实例是 nil 和 nonzero? - 如果数字是 0:

          if discount&.nonzero?
            # ...
          end
          

          或后缀:

          do_something if discount&.nonzero?
          

          【讨论】:

          • "foo"&.nonzero? # => NoMethodError: undefined method 'nonzero?' for "foo":String .... 这对任意对象使用是不安全的。
          • @TomLord,如前一条评论中所述,这不适用于任意对象。相反,它关注的是您知道应该是数字但也可能是 nil 的情况。
          • 我会在答案中明确说明这一事实,而不是让某人略读这篇文章而没有在 cmets 中发现免责声明。
          • @TomLord,在答案 "nonzero? 中说明 - 如果 number 是 0"。此外,与检查可能是也可能不是 nil 的数字相比,检查一个完全任意的对象是否是 0 的需求也很少出现。因此,它几乎是隐含的。即使有人以某种方式做出相反的假设,当他们尝试执行它时,他们也会立即明白发生了什么。
          【解决方案8】:

          在处理数据库记录时,我喜欢使用迁移助手将所有空值初始化为 0:

          add_column :products, :price, :integer, default: 0
          

          【讨论】:

            【解决方案9】:

            您可以利用NilClass 提供的#to_i 方法,该方法将为nil 值返回零:

            unless discount.to_i.zero?
              # Code here
            end
            

            如果discount 可以是小数,您可以改用#to_f,以防止数字被四舍五入为零。

            【讨论】:

            • 这和@oivoodo 的回答不一样吗?
            • 不适用于任意对象。 "".to_i == "foo".to_i == "0".to_i == 0。你的方法会产生各种意想不到的类型强制。如果discount 不响应to_i,它也会以NoMethodError 失败。
            【解决方案10】:

            您可以将空行转换为整数值并检查零吗?。

            "".to_i.zero? => true
            nil.to_i.zero? => true
            

            【讨论】:

            • 小心:0.1.to_i == 0
            【解决方案11】:
            除非 discount.nil? ||折扣 == 0 # ... 结尾

            【讨论】:

            • @yxi 但是根据那些准则,不是||在这种情况下首选选项?
            • 使用||,符号比文字更容易阅读。任何试图阅读应用题的人都会理解这些痛苦——只有在你用数学公式写出来之后才有意义。
            • 使用“或”是危险的。 'or' 的操作符出现率低于 '=',因此以下有意外行为:a = false 或 true #a 在此语句之后为 false
            • @xiy 目前指南建议假装 or and and and 不存在 (|| is that or && and?)
            • 当前的“Ruby 风格指南”代表The and and or keywords are banned. It's just not worth it. Always use && and || instead.。这是对的,出于大卫和汤姆的原因。
            【解决方案12】:
            if discount and discount != 0
              ..
            end
            

            更新,它将false 换成discount = false

            【讨论】:

              【解决方案13】:

              我相信以下对于 ruby​​ 代码来说已经足够好了。我不认为我可以编写一个单元测试来显示这与原始版本之间的任何区别。

              if discount != 0
              end
              

              【讨论】:

              • 如果折扣为nil,则计算结果为true。
              【解决方案14】:
              if (discount||0) != 0
                #...
              end
              

              【讨论】:

              • 这是我最喜欢的答案
              【解决方案15】:
              class Object
                def nil_zero?
                  self.nil? || self == 0
                end
              end
              
              # which lets you do
              nil.nil_zero? # returns true
              0.nil_zero?   # returns true
              1.nil_zero?   # returns false
              "a".nil_zero? # returns false
              
              unless discount.nil_zero?
                # do stuff...
              end
              

              当心通常的免责声明...巨大的权力/责任,猴子补丁导致黑暗面等。

              【讨论】:

                【解决方案16】:
                除非 [nil, 0].include?(折扣) # ... 结尾

                【讨论】:

                • 漂亮吗?是的。可读吗?不是真的。
                • 我觉得这完全可读,我更喜欢它而不是一个新类。干得好。
                • 处理两个条件的最 ruby​​ist 方法。
                【解决方案17】:

                你可以这样做:

                if (!discount.nil? && !discount.zero?)
                

                这里的顺序很重要,因为如果discount 是nil,那么它就没有zero? 方法。 Ruby 的短路评估应该阻止它尝试评估 discount.zero?,但是,如果 discount 是 nil。

                【讨论】:

                  【解决方案18】:

                  只要保证您的代码在初始化之前不会尝试使用它,您就可以将折扣初始化为 0。我想这会删除一张支票,我想不出别的了。

                  【讨论】:

                    猜你喜欢
                    • 1970-01-01
                    • 2015-10-24
                    • 2022-09-23
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2012-05-23
                    • 2017-03-06
                    相关资源
                    最近更新 更多