Bestes Rubin Idiom für „Null oder Null“
-
03-07-2019 - |
Frage
Ich suche nach einem kurzen Weg, um einen Wert zu überprüfen, um zu sehen, ob es gleich Null oder gleich Null ist. Zur Zeit mache ich so etwas wie:
if (!val || val == 0)
# Is nil or zero
end
Aber das scheint sehr ungeschickt.
Lösung
Objekte haben eine nil? Verfahren .
if val.nil? || val == 0
[do something]
end
Oder für nur eine Anweisung:
[do something] if val.nil? || val == 0
Andere Tipps
Wenn Sie wirklich, wie Methodennamen mit Fragezeichen am Ende:
if val.nil? || val.zero?
# do stuff
end
Ihre Lösung ist in Ordnung, wie einige der anderen Lösungen sind.
Rubin können Sie für eine hübsche Weise machen suchen, alles zu tun, wenn du nicht aufpasst.
Zunächst einmal denke ich, dass geht um die knappste Weise, die Sie für diesen bestimmten Zustand überprüfen.
Zweitens, das ist für mich einen Codegeruch, die eine potenzielle Schwachstelle in Ihrem Design zeigt. Im Allgemeinen nil und Null soll nicht das gleiche bedeuten. Wenn möglich, sollten Sie versuchen, die Möglichkeit, val sein null zu beseitigen, bevor Sie diesen Code getroffen, sei es durch, dass zu Beginn des Verfahrens oder einen anderen Mechanismus zu überprüfen.
versuchen, um loszuwerden, dieSie können einen völlig legitimen Grund müssen dies zu tun, in dem Fall, dass ich Ihr Code denken ist gut, aber ich würde zumindest prüfen Null zu überprüfen, wenn möglich.
von Ruby 2.3.0 weiter, können Sie den sicheren Navigation Operator kombinieren (&.
) mit Numeric#nonzero?
. &.
kehrt nil
, wenn die Instanz nil
und nonzero?
ist - wenn die Zahl ist 0
:
unless val&.nonzero?
# Is nil or zero
end
oder Postfix:
do_something unless val&.nonzero?
Sie können die Object.nil benutzen? für null zu testen, speziell (und nicht bekommen zwischen falschen und nil gefangen). Sie können Affen-Patch als auch ein Verfahren in Objekt.
class Object
def nil_or_zero?
return (self.nil? or self == 0)
end
end
my_object = MyClass.new
my_object.nil_or_zero?
==> false
Dies ist nicht als Änderungen empfohlen, Objekt schwierig für Mitarbeiter zu verfolgen, und können Ihren Code unvorhersehbar anderen.
Ich glaube, Ihr Code ist falsch; es wird für drei Werte in der Tat Test: nil
, false
, und Null. Dies liegt daran, die !val
Ausdruck für alle Werte wahr ist, die falsch sind, die in Ruby ist nil
und false
.
Das Beste, was ich mit jetzt kommen kann, ist
if val == nil || val == 0
# do stuff
end
Was natürlich nicht sehr klug, aber (sehr) klar.
nil.to_i gibt Null zurück, so dass ich oft tun:
val.to_i.zero?
Sie werden jedoch eine Ausnahme, wenn val je ein Objekt, das nicht respond_to #to_i der Fall ist.
Meine Lösung auch verwenden Ergebnis, abzüglich der conditionals.
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 tut dies über Attributabfragemethoden, in denen zusätzlich zu falschem und nil, 0 und „“ auch falsch zu bewerten.
if (model.attribute?) # => false if attribute is 0 and model is an ActiveRecord::Base derivation
Allerdings hat es seinen Anteil an Verleumder. http://www.joegrossberg.com/archives/002995.html
Um als idiomatisch wie möglich zu sein, würde ich dies vorschlagen.
if val.nil? or val == 0
# Do something
end
Denn:
- Es verwendet die Null? Verfahren.
- Es nutzt den "oder" Operator, der bevorzugt ist, ||.
- Es verwendet keine Klammern, die in diesem Fall nicht notwendig sind. Klammern sollten nur verwendet werden, wenn sie einen Zweck, wie zum Beispiel des Überschreiben des Vorrangs bestimmter Operatoren. dienen
Kürzeste und bester Weg, sollten
if val&.>(0)
# do something
end
Für val&.>(0)
es gibt null, wenn val nil da ist> im Grunde ist auch eine Methode, Null gleich falsch in rubin. Es return false wenn val == 0
.
Kurz und klar
[0, nil].include?(val)
ich damit umgehen durch die Definition eines „ist?“ Methode, die ich dann anders auf verschiedene Klassen implementieren kann. Also für Array „ist?“ bedeutet "size> 0"; für Fixnum bedeutet es "self = 0!"; für Streich bedeutet es „selbst! =‚‘“. NilClass, natürlich, definiert „ist?“ wie nur Null zurück.
Sie können case
verwenden, wenn Sie mögen:
case val with nil, 0
# do stuff
end
Dann können Sie etwas verwenden, das mit ===
funktioniert, was schön manchmal ist. Oder etwas tun, wie folgt aus:
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
Es ist nicht gerade gut OOP, aber es ist sehr flexibel und es funktioniert. Mein if
s in der Regel als case
s ohnehin enden.
Natürlich Enum.any?
/ Enum.include?
Art auch von funktioniert ... wenn man so will wirklich kryptisch bekommen:
if [0, nil].include? val
#do stuff
end
Das Richtige zu tun ist natürlich eine Methode oder eine Funktion zu definieren. Oder, wenn Sie die gleiche Sache mit vielen Werten zu tun haben, verwenden Sie eine Kombination dieser schönen Iteratoren.
Ich mag Rails blank?
Methode für diese Art von Dingen, aber es wird nicht true
für 0
zurück. So können Sie Ihre Methode hinzufügen:
def nil_zero?
if respond_to?(:zero?)
zero?
else
!self
end
end
Und es wird prüfen, ob irgendein Wert Null ist oder 0:
nil.nil_zero?
=> true
0.nil_zero?
=> true
10.nil_zero?
=> false
if val.nil_zero?
#...
end
Anstelle von Affen, der eine Klasse Patchen, könnte verwenden Verfeinerungen in Ruby 2.1 starten. Verfeinerungen sind ähnlich wie Affen Patchen; dass Sie ermöglichen Ihnen, die Klasse zu ändern, aber die Änderung ist begrenzt Sie auf den Umfang wollen es in verwenden.
Das ist übertrieben, wenn Sie diese Prüfung einmal tun wollen, aber wenn Sie sich selbst wiederholen ist es eine gute Alternative zu Affen Patchen.
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
Ergebnis wurde in letzter Minute geändert in die Datei scoped werden. So frühere Beispiele dies gezeigt haben, die nicht funktionieren.
class Car
using NilOrZero
end
Das ist sehr prägnant:
if (val || 0) == 0
# Is nil, false, or zero.
end
Es funktioniert, solange Sie nichts dagegen haben, false
die gleiche wie nil
behandeln. In den Projekten habe ich gearbeitet, nur diese Unterscheidung wichtig ist hin und wieder. Der Rest der Zeit persönlich ziehe ich .nil?
überspringen und etwas kürzer Code.
[ Aktualisieren : Ich schreibe nicht diese Art der Sache mehr. Es funktioniert, aber ist zu kryptisch. Ich habe versucht, Recht, meine Untaten zu setzen, indem sie die wenigen Stellen zu ändern, wo ich es tat.]
Übrigens, ich habe nicht .zero?
verwenden, da diese eine Ausnahme auslöst, wenn val
ist, sagen wir, eine Zeichenfolge. Aber .zero?
wäre schön, wenn Sie das ist nicht der Fall wissen.
Dies true ausgewertet für Null und Null: nil.to_s.to_d == 0
unless (val || 0).zero?
# do stufff
end
Eine andere Lösung:
if val.to_i == 0
# do stuff
end
val ||= 0
if val == 0
# do something here
end