我正在寻找一种简洁的方法来检查一个值,看它是否为零或零。目前我正在做类似的事情:
if (!val || val == 0)
# Is nil or zero
end
但这似乎很笨拙。
Answers:
对象有零?方法。
if val.nil? || val == 0
[do something]
end
或者,仅需一条指令:
[do something] if val.nil? || val == 0
or
此处的优先级不需要任何原谅,对于有经验的Rubyist来说,它会完全自然地读懂。唯一遭受过||
vsor
val && val == 0
更好。
如果您真的喜欢方法名称结尾带有问号:
if val.nil? || val.zero?
# do stuff
end
您的解决方案很好,其他解决方案也不错。
如果您不小心,Ruby可以使您搜索完成所有事情的漂亮方法。
从Ruby 2.3.0开始,您可以将安全导航运算符(&.
)与结合使用Numeric#nonzero?
。&.
返回nil
实例是否为-nil
和nonzero?
-如果数字为0
:
unless val&.nonzero?
# Is nil or zero
end
或后缀:
do_something unless val&.nonzero?
unless val&.nonzero?
意思是“如果val为零或零”
do_something if val&.nonzero?
(又名if val
is not nil
and not zero)。
首先,我认为这是您可以检查特定条件的最简洁方法。
其次,对我来说,这是一种代码气味,表明您的设计中存在潜在的缺陷。通常,nil和0不应表示同一件事。如果可能的话,您应该尝试在方法开始之前或其他某种机制进行检查,以消除val变为nil的可能性。
在这种情况下,您可能有一个完全合理的理由,在这种情况下,我认为您的代码是好的,但我至少会考虑尝试摆脱nil检查(如果可能)。
您可以使用Object.nil吗?具体测试是否为零(并且不会陷入false和nil之间)。您也可以将方法猴子插入对象。
class Object
def nil_or_zero?
return (self.nil? or self == 0)
end
end
my_object = MyClass.new
my_object.nil_or_zero?
==> false
不建议这样做,因为对同事的更改很难跟踪到对象,并且可能会使您的代码对其他人不可预测。
nil?
则将始终返回false。nil?
仅在NilClass上返回true。
Object
,NilClass
和Numeric
。Object
将返回false
,NilClass
将返回true
并且Numeric
将返回zero?
。
nil.to_i返回零,所以我经常这样做:
val.to_i.zero?
但是,如果val是不响应#to_i的对象,则将获得异常。
"5".to_i == 5, but you're more or less right. Clever but doesn't actually work
我的解决方案还使用优化,减去条件。
module Nothingness
refine Numeric do
alias_method :nothing?, :zero?
end
refine NilClass do
alias_method :nothing?, :nil?
end
end
using Nothingness
if val.nothing?
# Do something
end
Rails通过属性查询方法执行此操作,除false和nil之外,0和“”的求值结果也为false。
if (model.attribute?) # => false if attribute is 0 and model is an ActiveRecord::Base derivation
#attribute
,因为我找不到这样的东西。
为了尽可能地习惯,我建议这样做。
if val.nil? or val == 0
# Do something
end
因为:
简短明了
[0, nil].include?(val)
val.in? [0,nil]
case
如果愿意,可以使用:
case val with nil, 0
# do stuff
end
然后,您可以使用任何适用于的东西,===
有时候这很好。或执行以下操作:
not_valid = nil, 0
case val1 with *not_valid
# do stuff
end
#do other stuff
case val2 with *not_valid, false #Test for values that is nil, 0 or false
# do other other stuff
end
它不是很好的OOP,但是它非常灵活并且可以工作。无论如何,我if
通常都会以case
s结尾。
当然Enum.any?
/Enum.include?
某种类型的作品也...如果您想真正地获得神秘的话:
if [0, nil].include? val
#do stuff
end
正确的做法当然是定义方法或函数。或者,如果必须对多个值执行相同的操作,请结合使用这些不错的迭代器。
代替猴子修补类,您可以使用从Ruby 2.1开始的改进。提炼与猴子修补类似。这样,它们允许您修改类,但是修改仅限于您希望在其中使用的范围。
如果您只想进行一次此检查,那就太过分了,但是如果您要重复自己的话,这是猴子修补的绝佳选择。
module NilOrZero
refine Object do
def nil_or_zero?
nil? or zero?
end
end
end
using NilOrZero
class Car
def initialize(speed: 100)
puts speed.nil_or_zero?
end
end
car = Car.new # false
car = Car.new(speed: nil) # true
car = Car.new(speed: 0) # true
在最后一分钟更改了优化,以限制到文件范围。因此,较早的示例可能已经表明了这一点,但这将不起作用。
class Car
using NilOrZero
end
这很简洁:
if (val || 0) == 0
# Is nil, false, or zero.
end
只要您不介意false
与一样,它就会起作用nil
。在我从事的项目中,这种区别有时只是很重要。剩下的时间我个人更喜欢跳过,.nil?
并且代码略短。
[更新:我不再写这种东西了。它可以工作,但是太神秘了。我试图通过改变我做的几个地方来纠正我的错误行为。]
顺便说一句,我没有使用过,.zero?
因为这会引发异常val
,例如字符串。但是.zero?
,如果您知道不是这种情况,那会很好。
[edited]
我以为如果val
为零,那么此表达式的计算结果为nil == 0
(因此返回false
)。但是,它似乎确实起作用,尽管我认为它不是很可读。
另一个解决方案:
if val.to_i == 0
# do stuff
end
"5".to_i == 5
,但您或多或少是对的。聪明,但实际上不起作用。
val ||= 0
if val == 0
# do something here
end
val
需要保留in的值怎么办?您正在使用这种方法破坏输入数据,并且有更好的,破坏性较小的方法来检查nil或0。
false
怎样?