Ü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?

hectorsq
quelle
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
Dejan Simic
quelle
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.

Madlep
quelle
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.

umgeschrieben
quelle
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
Dejan Simic
quelle
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?
ndnenkov
quelle
"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
17
if (discount||0) != 0
  #...
end
Raimonds Simanovskis
quelle
Dies ist meine Lieblingsantwort
Wilson Freitas
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.

Jeremy Ruten
quelle
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
oivoodoo
quelle
Vorsicht: 0.1.to_i == 0
Simon B.
3
if discount and discount != 0
  ..
end

Update wird es falsefürdiscount = false

Rubyprince
quelle
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.

Dave GW
quelle
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.

Saroj
quelle
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
Pastullo
quelle
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.

Ed S.
quelle
0
if discount.nil? || discount == 0
  [do something]
end
Abhinay Reddy Keesara
quelle
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 .

Ozesh
quelle
-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
RichOrElse
quelle
-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
Jeff Waltzer
quelle
8
Es würde bewerten, trueob Rabatt wäre nil.
Andrew Grimm