Überprüfen, ob eine Variable in Ruby nicht Null und nicht Null ist


271

Ich verwende den folgenden Code, um zu überprüfen, ob eine Variable nicht Null und nicht Null ist

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

Gibt es einen besseren Weg, dies zu tun?


1
Wahrscheinlich, weil es sich um eine exakte Kopie von stackoverflow.com/questions/209495/… handelt .
David Nehme

1
Was soll es tun, wenn discountes falsch ist?
Andrew Grimm

1
Ich denke, discount.in? [0, nil]der sauberere Weg ist möglich
intmarinoreturn0

Antworten:


428
es sei denn, discount.nil? || Rabatt == 0
  # ...
Ende

31
Verwenden Sie 'oder' anstelle von ||
Orion Edwards

93
@ orion-edwards warum?
NARKOZ

39
Die Verwendung von 'oder' ist gefährlich. 'oder' hat eine geringere Operatorpräsenz als '=', daher hat Folgendes unerwartetes Verhalten: a = falsch oder wahr #a ist nach dieser Aussage falsch
Tom G

20
@xiy derzeit empfiehlt der Leitfaden vorzutäuschen oder und und existieren nicht (|| ist das oder && und?)
user3125280

67
Aktueller "Ruby Style Guide" steht The and and or keywords are banned. It's just not worth it. Always use && and || instead.. Und es ist richtig, aus Gründen von David und Tom.
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

Hüten Sie sich vor den üblichen Haftungsausschlüssen ... große Macht / Verantwortung, Affenflicken, die zur dunklen Seite führen usw.


28

ok, nachdem 5 Jahre vergangen sind ....

if discount.try :nonzero?
  ...
end

Es ist wichtig zu beachten, dass dies tryim ActiveSupport-Juwel definiert ist, sodass es nicht in einfachem Rubin verfügbar ist.


7
Beachten Sie, dass dies eine schienenspezifische Antwort ist. Vanille Rubin hat keine tryMethode.
Tom Lord

Richtig. Obwohl es eher ActiveSupport-spezifisch ist, ist es eine viel leichtere und weit verbreitete Abhängigkeit als die vollen Schienen. Wie auch immer, jetzt ist die Antwort von @ ndn die richtige.
Umgeschrieben am

Bearbeitet, um sichere Navigation zu verwenden
umgeschrieben am

1
Die Antwort dupliziert jetzt stackoverflow.com/a/34819818/1954610 ... Ich denke, es ist trysinnvoll, sie zu belassen, um die alternative Option anzuzeigen (aus diesem Grund wurde sie an erster Stelle positiv bewertet!), Solange dies klar ist der Leser, der ActiveSupportnicht Vanille Rubin ist.
Tom Lord

Punkt genommen, Antwort zurückgerollt.
umgeschrieben am

27
es sei denn [nil, 0] .include? (Rabatt) 
  # ...
Ende

13
Wunderschönen? Ja. Lesbar? Nicht wirklich.
El Ninja Trepador

1
Ich finde das perfekt lesbar und würde es einer neuen Klasse vorziehen. Gut gemacht.
Colincr

Der rubyistischste Ansatz, mit zwei Bedingungen umzugehen.
Yugendran

23

Ab Ruby 2.3.0 können Sie den sicheren Navigationsoperator ( &.) mit kombinieren Numeric#nonzero?. &.Gibt zurück, nilwenn die Instanz war nilund nonzero?- wenn die Nummer war 0:

if discount&.nonzero?
  # ...
end

Oder Postfix:

do_something if discount&.nonzero?

"foo"&.nonzero? # => NoMethodError: undefined method 'nonzero?' for "foo":String.... Dies ist nicht sicher für beliebige Objekte.
Tom Lord

2
@TomLord, wie im vorherigen Kommentar angegeben, sollte dies nicht mit beliebigen Objekten funktionieren. Stattdessen geht es um den Fall, dass Sie etwas haben, von dem Sie wissen, dass es eine Zahl sein sollte, aber möglicherweise auch nil.
ndnenkov

Ich würde diese Tatsache in der Antwort klarstellen, anstatt dass jemand dies überfliegt und den Haftungsausschluss in den Kommentaren nicht entdeckt.
Tom Lord

@ TomLord, es wird in der Antwort " nonzero?- wenn die Nummer war 0" angegeben . Auch die Notwendigkeit zu prüfen, ob ein völlig beliebiges Objekt 0vorliegt, tritt im Vergleich zu dem, was eine Zahl sein kann oder nicht, äußerst selten auf nil. Daher ist es fast impliziert. Selbst wenn jemand irgendwie die gegenteilige Annahme macht, wird er sofort verstehen, was passiert, wenn er versucht, es auszuführen.
ndnenkov


15

Sie könnten dies tun:

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

Die Reihenfolge ist hier wichtig, denn wenn discountja nil, dann hat es keine zero?Methode. Die Kurzschlussbewertung von Ruby sollte jedoch verhindern, dass versucht wird, eine Bewertung discount.zero?vorzunehmen, wenn dies der Fall discountist nil.


11

Sie können Ihre leere Zeile in einen ganzzahligen Wert konvertieren und Null prüfen.

"".to_i.zero? => true
nil.to_i.zero? => true

Vorsicht: 0.1.to_i == 0
Simon B.

3
if discount and discount != 0
  ..
end

Update wird es falsefürdiscount = false


2

Sie können die NilClassbereitgestellte #to_iMethode nutzen, die für nilWerte Null zurückgibt:

unless discount.to_i.zero?
  # Code here
end

Wenn es discountsich um Bruchzahlen handeln kann, können Sie #to_fstattdessen verwenden, um zu verhindern, dass die Zahl auf Null gerundet wird.


Ist das nicht dasselbe wie die Antwort von @ oivoodo?
Cary Swoveland

Funktioniert nicht für beliebige Objekte . "".to_i == "foo".to_i == "0".to_i == 0. Ihre Methode macht alle Arten von unbeabsichtigten Zwängen. Es wird auch mit einem NoMethodErrorif fehlschlagen, auf discountdas nicht reagiert wird to_i.
Tom Lord

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

Wenn wir "" bestehen, wird false zurückgegeben, während leer? gibt true zurück. Gleiches gilt für data = false blank? Gibt true für nil, false, empty oder eine Leerzeichenfolge zurück. Also ist es besser, leer zu verwenden? Methode, um auch leere Zeichenfolgen zu vermeiden.


1
blank?ist eine schienenspezifische Methode und nicht in Vanille-Rubin erhältlich.
Tom Lord

Du hast Recht!! Ich dachte, dass dies mit dem hier geposteten "ror" -Tag zusammenhängt. Mein Fehler. Dies wird in Vanille-Rubin nicht funktionieren.
Saroj

1

Wenn ich mich mit einem Datenbankeintrag befasse , möchte ich alle leeren Werte mit dem Migrationshelfer mit 0 initialisieren:

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

0

Sie können den Rabatt auf 0 initialisieren, solange Ihr Code garantiert nicht versucht, ihn zu verwenden, bevor er initialisiert wird. Das würde einen Scheck entfernen, ich denke, ich kann mir nichts anderes vorstellen.



0

Ich bevorzuge einen saubereren Ansatz:

val.to_i.zero?

val.to_igibt a zurück, 0wenn val a ist nil,

Danach müssen wir nur noch prüfen, ob der Endwert Null ist .


-1

Eine alternative Lösung besteht darin, Verfeinerungen wie folgt zu verwenden:

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

Ich glaube, das Folgende ist gut genug für Ruby-Code. Ich glaube nicht, dass ich einen Unit-Test schreiben könnte, der einen Unterschied zwischen diesem und dem Original zeigt.

if discount != 0
end

8
Es würde bewerten, trueob Rabatt wäre nil.
Andrew Grimm
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.