Rubyで変数がnilでも0でもないことを確認する


271

次のコードを使用して、変数がnilでもゼロでもないかどうかを確認しています

if(discount != nil && discount != 0) 
  ...
end

これを行うより良い方法はありますか?


1
おそらくそれがstackoverflow.com/questions/209495/…の正確なコピーであるためです。
David Nehme、2008年

1
discountfalseの場合はどうすればよいですか?
Andrew Grimm、

1
よりdiscount.in? [0, nil]クリーンな方法が可能だと思います
intmarinoreturn0

回答:


428
discount.nilでない限り?|| 割引== 0
  #...
終わり

31
||の代わりに「または」を使用します
オリオンエドワーズ

93
@ orion-edwardsなんで?
NARKOZ、2011

39
「または」の使用は危険です。「または」は「=」より演算子の優先順位が低いため、次のような予期しない動作があります:a = falseまたはtrue #aはこのステートメントの後でfalseです
Tom G

20
@xiyは現在、orとandとandは存在しないふりをすることを推奨しています(||か、&& and?)
user3125280

67
現在の「Rubyスタイルガイド」の略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

わかりました、5年が経過した後...

if discount.try :nonzero?
  ...
end

tryはActiveSupport gemで定義されているため、プレーンルビでは使用できないことに注意してください。


7
これはRails固有の回答であることに注意してください。バニラルビーにはtryメソッドがありません。
トム卿

正しい。これは、ActiveSupport固有のものに似ていますが、フルレールよりもはるかに軽量で広く使用されている依存関係です。とにかく今@ndnの応答は正しいものです。
2017年

安全なナビゲーションを使用するように編集
書き換え

1
答えは現在、stackoverflow.comtry / a / 34819818/1954610 と重複しています... 代替オプションを示すためにそのままにしておくことには価値があると思います(これが最初から支持されていた理由です!)。ActiveSupportバニラルビーではない読者。
トム・ロード

ポイントを取って、答えをロールバックしました。
書き換え

27
[nil、0] .include?(discount)以外 
  #...
終わり

13
綺麗な?はい。読める?あんまり。
El Ninja Trepador 2016年

1
私はこれが完全に読みやすいと思います、そして私は新しいクラスよりもそれを好みます。よくやった。
colincr 2018年

2つの条件を処理する最もルビイストなアプローチ。
Yugendran

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....これは、任意のオブジェクトで使用するのは安全ではありません。
Tom Lord

2
@TomLordは、前のコメントで述べたように、任意のオブジェクトを処理することを目的としていませんでした。代わりに、数値である必要があるとわかっているものがある場合に関係がありますが、そうでない場合もありますnil
ndnenkov 2017

誰かがこれを読み飛ばしてコメントに免責事項を見つけないのではなく、答えでその事実を明確にします。
トム卿

@TomLord、それが答えに記載されているnonzero?-あれば数はでした0。また、完全に任意のオブジェクトが存在0するかどうかを確認する必要性は、そうでない可能性があるかどうかに関係なく、数を確認する場合と比較して非常にまれに発生しますnil。したがって、それはほとんど暗示されています。誰かが何らかの理由で逆の仮定を行ったとしても、彼らはそれを実行しようとしたときに何が起こっているかを即座に理解します。
ndnenkov 2017


15

あなたはこれを行うことができます:

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

場合ので順番は、ここで重要なのdiscountであるnil、それはありませんzero?方法を。Rubyのショートサーキット評価は、評価しようとするのを妨げるはずdiscount.zero?ですdiscountが、もしそうならnil


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の回答と同じではありませんか?
Cary Swoveland、2015年

任意のオブジェクトに対しては機能しません"".to_i == "foo".to_i == "0".to_i == 0。このメソッドは、あらゆる種類の意図しない型の強制変換を行います。NoMethodErrorif discountが応答しない場合も失敗しto_iます。
トム主

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

「」を渡すと、空白であるのにfalseを返しますか?trueを返します。data = falseの場合も同じです。nil、false、空、または空白文字列に対してtrueを返します。だからブランクを使う方がいいですか?空の文字列も回避するメソッド。


1
blank?はレール固有のメソッドであり、バニラ・ルビーでは使用できません。
Tom Lord

あなたは正しいです!!これは "ror"タグに関連していると思ったので、ここに投稿しました。私の間違い。これはバニラルビーでは機能しません。
Saroj 2017年

1

データベースレコードを処理するとき、移行ヘルパーを使用して、すべての空の値を0で初期化します。

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

0

コードが初期化される前にそれを試して使用しないことが保証されている限り、割引を0に初期化できます。それは私が仮定する1つのチェックを取り除くでしょう、私は他に何も考えることができません。



0

私はよりクリーンなアプローチを好む:

val.to_i.zero?

val.to_i返され0た場合valがありnil

その後、最終的な値がゼロかどうかを確認するだけです


-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、
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.