“零或零”的最佳红宝石习语
-
03-07-2019 - |
题
我正在寻找一种简洁的方法来检查值是否为零或零。目前我正在做类似的事情:
if (!val || val == 0)
# Is nil or zero
end
但这看起来非常笨拙。
解决方案
对象有 nil?方法。
if val.nil? || val == 0
[do something]
end
或者,只需一条指令:
[do something] if val.nil? || val == 0
其他提示
如果您真的喜欢最后带问号的方法名称:
if val.nil? || val.zero?
# do stuff
end
您的解决方案很好,其他一些解决方案也是如此。
如果你不小心的话,Ruby可以让你搜索一个很好的方法去做所有事情。首先,我认为这是您可以检查特定情况的最简洁方式。
其次,对我而言,这是一种代码气味,表明您的设计存在潜在缺陷。通常零和零不应该意味着相同的事情。如果可能的话,你应该尝试在你点击这个代码之前消除val为零的可能性,或者通过检查方法的开头或其他一些机制。
你可能有一个完全合理的理由这样做,在这种情况下我认为你的代码是好的,但我至少考虑试图摆脱零检查,如果可能的话。
从Ruby 2.3.0开始,您可以将安全导航操作符(&。
)与 Numeric#nonzero?
。 &。
返回 nil
,如果实例是 nil
而非零?
- 如果数字是 0 代码>:
unless val&.nonzero?
# Is nil or zero
end
或后缀:
do_something unless val&.nonzero?
你可以使用Object.nil吗?特别测试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
,并且为零。这是因为!val
表达式对于所有false值都是true,在Ruby中是 nil
和 false
。
我现在能想到的最好的是
if val == nil || val == 0
# do stuff
end
当然,这不是很聪明,但(非常)清楚。
nil.to_i返回零,所以我经常这样做:
val.to_i.zero?
但是,如果val是一个不响应#to_i的对象,你将得到一个例外。
我的解决方案也使用Refinements,减去条件。
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和“"”之外。也评价为假。
if (model.attribute?) # => false if attribute is 0 and model is an ActiveRecord::Base derivation
然而,它有其批评者的份额。 http://www.joegrossberg.com/archives/002995.html 为了尽可能地惯用,我建议这样做。
if val.nil? or val == 0
# Do something
end
因为:
- 它使用零?方法。
- 它使用“或”运算符,这比 || 更好。
- 它不使用括号,在本例中不需要括号。括号仅应在用于某些目的时使用,例如覆盖某些运算符的优先级。
最短且最好的方式应该是
if val&.>(0)
# do something
end
val&。>(0)
当val为零时,它返回nil,因为>基本上也是一个方法,在ruby中nil等于false。当 val == 0
时,它返回false。
简短明了
[0,nil] .include?(val)
我通过定义“is?”来解决这个问题。方法,然后我可以在各种类上实现不同的方法。所以对于Array,“是吗?”表示“尺寸> 0”;对于Fixnum,它意味着“self!= 0”;对于String,它表示“self!=''”。当然,NilClass定义“是?”。就像刚回来一样。
您可以使用 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
s 通常最终会变成 case
无论如何。
当然 Enum.any?
/Enum.include?
也有类似的作品...如果你想变得更加神秘:
if [0, nil].include? val
#do stuff
end
正确的做法当然是定义一个方法或函数。或者,如果您必须对许多值执行相同的操作,请使用这些不错的迭代器的组合。
我真的很喜欢Rails blank?
这种方法,但它不会返回 0
的 true
。所以你可以添加你的方法:
def nil_zero?
if respond_to?(:zero?)
zero?
else
!self
end
end
它将检查某些值是否为0或<:p>
nil.nil_zero?
=> true
0.nil_zero?
=> true
10.nil_zero?
=> false
if val.nil_zero?
#...
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?
会很好,如果你知道情况并非如此。
对于nil和零,计算结果为true: nil.to_s.to_d == 0
unless (val || 0).zero?
# do stufff
end
另一种解决方案:
if val.to_i == 0
# do stuff
end
val ||= 0
if val == 0
# do something here
end