检查变量是否不是nil并且在ruby中不为零


Answers:


428
除非discount.nil?|| 折扣== 0
  #...
结束

31
使用“或”代替||
Orion Edwards

93
@ orion-edwards为什么?
NARKOZ 2011年

39
使用“或”是危险的。“或”比“ =”具有较低的运算符优先级,因此以下内容具有意外的行为:a = false或true #a在此语句后为false
Tom G

20
@xiy当前指南建议假装or和and不存在(||是or &&和?)
user3125280 2014年

67
当前的“ Ruby Style Guide”立场The and and or keywords are banned. It's just not worth it. Always use && and || instead.。没错,出于大卫和汤姆的原因。
Andre Figueiredo

40
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

提防通常的免责声明...强大的权力/责任感,猴子修补导致黑暗的一面等。


28

好,五年过去了。

if discount.try :nonzero?
  ...
end

重要的是要注意,它try是在ActiveSupport gem中定义的,因此在纯红宝石中不可用。


7
请注意,这是特定Rails的答案。香草红宝石没有try方法。
汤姆勋爵

正确。尽管它更像特定于ActiveSupport的,但它比完整的导轨要轻得多且使用广泛。无论如何,@ ndn的回复是正确的。
重写

编辑使用安全导航
重写

1
现在,答案是重复的stackoverflow.com/a/34819818/1954610 ...我认为保留它的价值是try可以显示替代选项的(这就是为什么它一开始就被否决了!),只要清楚读者ActiveSupport不是香草红宝石。
汤姆·罗德,

点了,答案回滚了。
重写


23

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

if discount&.nonzero?
  # ...
end

或后缀:

do_something if discount&.nonzero?

"foo"&.nonzero? # => NoMethodError: undefined method 'nonzero?' for "foo":String....在任意对象上使用都不安全。
汤姆·罗德

2
如上一条注释所述,@ TomLord不适用于任意对象。取而代之的是,当您知道某些东西应该是一个数字,但也可能是时,它与情况有关nil
ndnenkov

我会在回答中清楚地表明这一事实,而不是让别人略读它,而不在评论中发现免责声明。
汤姆·罗德

@TomLord,在回答nonzero?-如果数字0”中指出。0与检查可能存在或可能不存在的数字相比,很少需要检查是否存在完全任意的对象nil。因此,几乎暗示了这一点。即使某人以某种方式做出了相反的假设,当他们尝试执行该假设时,他们也会立即了解正在发生的事情。
ndnenkov


15

您可以这样做:

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

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


11

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

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

注意:0.1.to_i == 0
Simon B.


2

您可以利用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。您的方法将进行各种意外类型的强制转换。NoMethodError如果discount不响应,也会失败to_i
汤姆·罗德

2
def is_nil_and_zero(data)
     data.blank? || data == 0 
end  

如果我们传递“”,它将返回false而不是空白?返回true。数据=假空白时,情况也是如此?对于nil,false,empty或空白字符串返回true。所以最好使用空白?避免空字符串的方法。


1
blank?是特定于Rails的方法,在香草红宝石中不可用。
汤姆·罗德

你是对的!!我认为这与在此处发布的“ ror”标签有关。我的错。这不适用于香草红宝石。
Saroj

1

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

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

0

您可以将折扣初始化为0,只要保证您的代码在初始化之前不要尝试使用它即可。我想那会删除一张支票,我想不起其他任何东西。



0

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

val.to_i.zero?

val.to_i0如果val是a nil,则将返回a

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


-1

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

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

-7

我相信以下对于Ruby代码已经足够了。我不认为我可以编写一个单元测试来显示此版本与原始版本之间的任何差异。

if discount != 0
end

8
它会评估true是否有折扣nil
Andrew Grimm'3
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.