Ich suche nach einer präzisen Möglichkeit, einen Wert zu überprüfen, um festzustellen, ob er Null oder Null ist. Zur Zeit mache ich so etwas wie:
if (!val || val == 0)
# Is nil or zero
end
Aber das scheint sehr ungeschickt.
Antworten:
Objekte haben eine Null? Methode .
if val.nil? || val == 0
[do something]
end
Oder für nur eine Anweisung:
[do something] if val.nil? || val == 0
or
erfordert hier keine Parens und wird einem erfahrenen Rubyisten ganz natürlich vorlesen. Die einzigen Menschen , die jemals gebissen werden durch ||
Vergleich or
sind Menschen , die nie Perl programmiert haben :)
val && val == 0
ist besser.
Wenn Sie Methodennamen mit Fragezeichen am Ende wirklich mögen:
if val.nil? || val.zero?
# do stuff
end
Ihre Lösung ist in Ordnung, ebenso wie einige der anderen Lösungen.
Ruby kann Sie dazu bringen, nach einem hübschen Weg zu suchen, um alles zu tun, wenn Sie nicht vorsichtig sind.
Ab Ruby 2.3.0 können Sie den sicheren Navigationsoperator ( &.
) mit kombinieren Numeric#nonzero?
. &.
Gibt zurück, nil
wenn die Instanz war nil
und nonzero?
- wenn die Nummer war 0
:
unless val&.nonzero?
# Is nil or zero
end
Oder Postfix:
do_something unless val&.nonzero?
unless val&.nonzero?
um zu verstehen, was übersetzt "wenn val null oder null ist" bedeutet
do_something if val&.nonzero?
(auch bekannt als if val
is not nil
und not zero).
Zunächst einmal denke ich, dass dies die präziseste Art ist, wie Sie nach dieser bestimmten Bedingung suchen können.
Zweitens ist dies für mich ein Code-Geruch, der auf einen möglichen Fehler in Ihrem Design hinweist. Im Allgemeinen sollten Null und Null nicht dasselbe bedeuten. Wenn möglich, sollten Sie versuchen, die Möglichkeit auszuschließen, dass val Null ist, bevor Sie diesen Code drücken, indem Sie dies entweder zu Beginn der Methode oder durch einen anderen Mechanismus überprüfen.
Möglicherweise haben Sie einen absolut legitimen Grund, dies zu tun. In diesem Fall halte ich Ihren Code für gut, aber ich würde zumindest in Betracht ziehen, den Null-Check nach Möglichkeit loszuwerden.
Sie können die Object.nil? spezifisch auf Null zu testen (und nicht zwischen falsch und Null gefangen zu werden). Sie können eine Methode auch in Object patchen.
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 wird nicht empfohlen, da Änderungen an Object für Mitarbeiter schwer nachzuvollziehen sind und Ihr Code für andere möglicherweise unvorhersehbar ist.
nil?
würde immer false zurückgeben. nil?
Gibt nur in der NilClass true zurück.
Object
, NilClass
und Numeric
. Object
würde zurückkehren false
, NilClass
würde zurückkehren true
und Numeric
würde zurückkehren zero?
.
nil.to_i gibt Null zurück, deshalb mache ich das oft:
val.to_i.zero?
Sie erhalten jedoch eine Ausnahme, wenn val jemals ein Objekt ist, das nicht auf #to_i reagiert.
"5".to_i == 5, but you're more or less right. Clever but doesn't actually work
Ich glaube, Ihr Code ist falsch. es wird für drei Werte in der Tat Test: nil
, false
und null. Dies liegt daran, dass der !val
Ausdruck für alle Werte wahr ist, die falsch sind, was in Ruby nil
und ist false
.
Das Beste, was ich mir gerade einfallen lassen kann, ist
if val == nil || val == 0
# do stuff
end
Was natürlich nicht sehr klug ist, aber (sehr) klar.
Meine Lösung verwendet auch Verfeinerungen abzüglich der Bedingungen.
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, wobei neben false und nil auch 0 und "" als false ausgewertet werden.
if (model.attribute?) # => false if attribute is 0 and model is an ActiveRecord::Base derivation
Es hat jedoch seinen Anteil an Kritikern. http://www.joegrossberg.com/archives/002995.html
#attribute
, weil ich so etwas nicht finden kann.
Um so idiomatisch wie möglich zu sein, würde ich dies vorschlagen.
if val.nil? or val == 0
# Do something
end
Weil:
Kurz und klar
[0, nil].include?(val)
val.in? [0,nil]
Der kürzeste und beste Weg sollte sein
if val&.>(0)
# do something
end
Denn val&.>(0)
es gibt nil zurück, wenn val nil ist, da> im Grunde auch eine Methode ist, nil gleich false in ruby. Es gibt false zurück, wenn val == 0
.
Ich gehe damit um, indem ich ein "ist?" Methode, die ich dann auf verschiedenen Klassen unterschiedlich implementieren kann. Also für Array "ist?" bedeutet "Größe> 0"; für Fixnum bedeutet es "self! = 0"; für String bedeutet es "self! = ''". NilClass definiert natürlich "ist?" als nur Null zurück.
Sie können verwenden, case
wenn Sie möchten:
case val with nil, 0
# do stuff
end
Dann können Sie alles verwenden, was funktioniert ===
, was manchmal schön ist. Oder machen Sie so etwas:
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 endet normalerweise case
sowieso als s.
Natürlich Enum.any?
/ Enum.include?
Art funktioniert auch ... wenn Sie wirklich kryptisch werden möchten:
if [0, nil].include? val
#do stuff
end
Das Richtige ist natürlich, eine Methode oder Funktion zu definieren. Wenn Sie dasselbe mit vielen Werten tun müssen, verwenden Sie eine Kombination dieser netten Iteratoren.
Ich mag Rails blank?
Methode für diese Art von Dingen, aber es wird nicht wieder true
für 0
. So können Sie Ihre Methode hinzufügen:
def nil_zero?
if respond_to?(:zero?)
zero?
else
!self
end
end
Und es wird geprüft, ob ein Wert Null oder 0 ist:
nil.nil_zero?
=> true
0.nil_zero?
=> true
10.nil_zero?
=> false
if val.nil_zero?
#...
end
Anstatt eine Klasse mit Affen zu patchen, können Sie ab Ruby 2.1 Verfeinerungen verwenden . Verfeinerungen ähneln dem Patchen von Affen. Auf diese Weise können Sie die Klasse ändern, die Änderung ist jedoch auf den Bereich beschränkt, in dem Sie sie verwenden möchten.
Dies ist übertrieben, wenn Sie diese Überprüfung einmal durchführen möchten, aber wenn Sie sich wiederholen, ist dies eine großartige Alternative zum Affen-Patching.
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
Die Verfeinerungen wurden in letzter Minute geändert , um sie in die Datei aufzunehmen. Frühere Beispiele haben dies möglicherweise gezeigt, was jedoch nicht funktioniert.
class Car
using NilOrZero
end
Das ist sehr prägnant:
if (val || 0) == 0
# Is nil, false, or zero.
end
Es funktioniert so lange, wie es Ihnen nichts ausmacht, false
dasselbe zu behandeln wie nil
. In den Projekten, an denen ich gearbeitet habe, ist diese Unterscheidung nur gelegentlich von Bedeutung. Den Rest der Zeit überspringe ich persönlich lieber .nil?
und habe etwas kürzeren Code.
[ Update : Ich schreibe so etwas nicht mehr. Es funktioniert, ist aber zu kryptisch. Ich habe versucht, meine Missetaten zu korrigieren, indem ich die wenigen Stellen geändert habe, an denen ich es getan habe.]
Übrigens habe ich nicht verwendet, .zero?
da dies eine Ausnahme auslöst val
, wenn es sich beispielsweise um eine Zeichenfolge handelt. Aber .zero?
wäre in Ordnung, wenn Sie wissen, dass dies nicht der Fall ist.
[edited]
Ich dachte, wenn val
Null wäre, würde dieser Ausdruck zu nil == 0
(und damit zurückkehren false
) führen. Es scheint jedoch, dass es tatsächlich funktioniert, obwohl ich es nicht für sehr lesbar halte.
Eine andere Lösung:
if val.to_i == 0
# do stuff
end
"5".to_i == 5
, aber du hast mehr oder weniger recht. Clever, funktioniert aber nicht.
val ||= 0
if val == 0
# do something here
end
val
beibehalten werden muss? Mit dieser Methode werden die Eingabedaten überlastet, und es gibt bessere, weniger zerstörerische Möglichkeiten, um auf Null oder Null zu prüfen.
false
?