web-dev-qa-db-ja.com

Best Ruby "nil or zero"のイディオム

値がnilかゼロかを確認するための値をチェックする簡潔な方法を探しています。現在、私は次のようなことをしています:

if (!val || val == 0)
  # Is nil or zero
end

しかし、これは非常に不器用なようです。

73
csexton

オブジェクトには nil?メソッド があります。

if val.nil? || val == 0
  [do something]
end

または、たった1つの指示で:

[do something] if val.nil? || val == 0
67

最後に疑問符が付いたメソッド名が本当に好きな場合:


if val.nil? || val.zero?
  # do stuff
end

他のいくつかのソリューションと同様に、ソリューションは問題ありません。

Rubyを使用すると、気をつけなければ、すべてを行うためのきれいな方法を検索できます。

32
MilesZS

まず、その特定の状態をチェックできる最も簡潔な方法だと思います。

第二に、これはコードの匂いであり、デザインの潜在的な欠陥を示しています。通常、nilとzeroは同じことを意味するべきではありません。可能であれば、このコードをヒットする前に、メソッドの先頭またはその他のメカニズムでチェックすることにより、valがnilになる可能性を排除する必要があります。

あなたはこれを行う完全に正当な理由があるかもしれません。その場合、私はあなたのコードは良いと思いますが、可能な限りnilチェックを取り除くことを試みることを少なくとも考えています。

29
Mike Deck

Ruby 2.3.0以降では、安全なナビゲーション演算子(_&._)と _Numeric#nonzero?_ を組み合わせることができます。_&._戻り値nilインスタンスがnilおよび_nonzero?_の場合-番号が_0_の場合:

_unless val&.nonzero?
  # Is nil or zero
end
_

または後置:

_do_something unless val&.nonzero?
_
24
ndnenkov

Object.nilを使用できますか?特にnilをテストします(falseとnilの間に追いつかないようにします)。メソッドをObjectにモンキーパッチすることもできます。

class Object
   def nil_or_zero?
     return (self.nil? or self == 0)
   end
end

my_object = MyClass.new
my_object.nil_or_zero?
==> false

Objectの変更は同僚が追跡するのが難しく、コードが他の人に予測不可能になる可能性があるため、これは推奨されません。

9
Adrian Dunston

nil.to_iはゼロを返すので、私はしばしばこれを行います:

val.to_i.zero?

ただし、valが#to_iに応答しないオブジェクトである場合、例外が発生します。

4
ntl

あなたのコードは間違っていると思います。実際には、nilfalse、ゼロの3つの値をテストします。これは、!val式は、Rubyでnilおよびfalseであるfalseのすべての値に対してtrueです。

私が今思いつくことができる最高のものは

if val == nil || val == 0
  # do stuff
end

もちろん、これはあまり賢いわけではありませんが、(非常に)明確です。

4
unwind

私のソリューションでは、条件を除いた絞り込みも使用しています。

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
3
RichOrElse

Railsはこれを、属性クエリメソッドを介して実行します。falseとnilに加えて、0と ""もfalseと評価されます。

if (model.attribute?) # => false if attribute is 0 and model is an ActiveRecord::Base derivation

しかし、それは中傷者の割合を持っています。 http://www.joegrossberg.com/archives/002995.html

2
Gishu

可能な限りイディオムにするには、これをお勧めします。

if val.nil? or val == 0
    # Do something
end

なぜなら:

  • Nilを使用しますか?方法。
  • 「または」演算子を使用します。これは||よりも望ましいです。
  • この場合は必要ない括弧を使用しません。括弧は、特定の演算子の優先順位をオーバーライドするなど、何らかの目的に役立つ場合にのみ使用してください。
2
Joshua Swink

最短で最良の方法は

_if val&.>(0)
  # do something
end
_

val&.>(0)の場合、valはnilであるときにnilを返します。これは、>も基本的にメソッドであり、Rubyではnilがfalseに等しいためです。 _val == 0_の場合はfalseを返します。

2
user2097847

短くて明確

[0, nil].include?(val)

1
Stanislav Kr.

これは非常に簡潔です:

if (val || 0) == 0
  # Is nil, false, or zero.
end

falsenilと同じように扱うことを気にしない限り機能します。私が取り組んだプロジェクトでは、その区別はたまにしか重要ではありません。残りの時間は個人的に.nil?をスキップし、コードを少し短くすることを好みます。

[更新:この種のことはもう書かない。それは動作しますが、あまりにも不可解です。私はそれをしたいくつかの場所を変えることによって、私の悪行を正そうと試みました。]

ちなみに、valが文字列の場合は例外が発生するため、.zero?は使用しませんでした。ただし、そうでないことがわかっている場合は、.zero?で十分です。

0
antinome

サルがクラスにパッチを適用する代わりに、 洗練を使用できます で始まるRuby 2.1。洗練はサルのパッチに類似しています。ただし、変更は使用する範囲に制限されます。

このチェックを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
0
Mohamad

必要に応じて、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は通常とにかくcasesになります。

もちろんEnum.any?/Enum.include?の種類の作品も...もしあなたが本当に謎めいたものを得たいなら:

if [0, nil].include? val
    #do stuff
end

もちろん正しい方法は、メソッドまたは関数を定義することです。または、多くの値で同じことを行う必要がある場合は、これらのNiceイテレーターの組み合わせを使用します。

0
martin

これは、nilおよびゼロに対してtrueと評価されます。nil.to_s.to_d == 0

0
Sam
unless (val || 0).zero?

    # do stufff

end
0
Abel

私はRails blank?メソッドが好きなのですが、0に対してtrueを返しません。メソッドを追加できます:

def nil_zero? 
  if respond_to?(:zero?) 
    zero? 
  else 
    !self 
  end 
end 

そして、ある値がnilか0かをチェックします:

nil.nil_zero?
=> true
0.nil_zero?
=> true
10.nil_zero?
=> false

if val.nil_zero?
  #...
end
0
klew

これに対処するには、「is?」を定義します。このメソッドは、さまざまなクラスで異なる方法で実装できます。したがって、配列の場合、「?」 「サイズ> 0」を意味します。 Fixnumの場合、「self!= 0」を意味します。 Stringの場合、「self!= ''」を意味します。もちろん、NilClassは「is?」を定義します単にnilを返すように。

0
glenn mcdonald