我正在寻找一种简洁的方法来检查值是否为零或零。目前我正在做类似的事情:

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,但它非常灵活并且有效。我的 ifs 通常最终会变成 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
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top