Szukam zwięzłego sposobu sprawdzenia wartości, aby sprawdzić, czy jest zerowa lub zerowa. Obecnie robię coś takiego:
if (!val || val == 0)
# Is nil or zero
end
Ale to wydaje się bardzo niezdarne.
ruby
design-patterns
idioms
null
csexton
źródło
źródło
false
?Odpowiedzi:
Obiekty mają zero? metoda .
if val.nil? || val == 0 [do something] end
Lub dla jednej instrukcji:
[do something] if val.nil? || val == 0
źródło
or
nie wymaga tutaj żadnych odwołań i będzie czytane całkowicie naturalnie dla doświadczonego Rubyisty. Jedynymi ludźmi, którzy kiedykolwiek zostali ugryzieni przez||
versus,or
są ludzie, którzy nigdy nie zaprogramowali Perla :)val && val == 0
jest lepiej.Jeśli naprawdę lubisz nazwy metod ze znakami zapytania na końcu:
if val.nil? || val.zero? # do stuff end
Twoje rozwiązanie jest w porządku, podobnie jak kilka innych rozwiązań.
Ruby może sprawić, że będziesz szukał ładnego sposobu na zrobienie wszystkiego, jeśli nie będziesz ostrożny.
źródło
Począwszy od Rubiego 2.3.0, możesz łączyć bezpieczny operator nawigacji (
&.
) zNumeric#nonzero?
.&.
zwraca,nil
jeśli wystąpienie byłonil
inonzero?
- jeśli liczba to0
:unless val&.nonzero? # Is nil or zero end
Lub postfix:
do_something unless val&.nonzero?
źródło
unless val&.nonzero?
przekłada się na "jeśli val wynosi zero lub zero"do_something if val&.nonzero?
(aka, jeślival
nie jestnil
i nie jest zerem).Po pierwsze, myślę, że to najbardziej zwięzły sposób na sprawdzenie tego konkretnego stanu.
Po drugie, dla mnie jest to zapach kodu, który wskazuje na potencjalną wadę twojego projektu. Generalnie zero i zero nie powinny oznaczać tego samego. Jeśli to możliwe, powinieneś spróbować wyeliminować możliwość, że val będzie zerowa, zanim trafisz na ten kod, albo sprawdzając to na początku metody, albo przez inny mechanizm.
Możesz mieć całkowicie uzasadniony powód, aby to zrobić, w takim przypadku myślę, że twój kod jest dobry, ale przynajmniej rozważę próbę pozbycia się sprawdzania zerowego, jeśli to możliwe.
źródło
Możesz użyć Object.nil? specjalnie przetestować na zero (i nie dać się złapać między fałszem a zerem). Możesz również łączyć metodę w Object.
class Object def nil_or_zero? return (self.nil? or self == 0) end end my_object = MyClass.new my_object.nil_or_zero? ==> false
Nie jest to zalecane, ponieważ zmiany w Object są trudne do śledzenia dla współpracowników i mogą spowodować, że Twój kod będzie nieprzewidywalny dla innych.
źródło
nil?
zawsze zwróci false.nil?
zwraca tylko wartość true w NilClass.Object
,NilClass
iNumeric
.Object
wrócifalse
,NilClass
wrócitrue
iNumeric
wrócizero?
.nil.to_i zwraca zero, więc często robię to:
Jednak otrzymasz wyjątek, jeśli val kiedykolwiek będzie obiektem, który nie odpowiada na #to_i.
źródło
"5".to_i == 5, but you're more or less right. Clever but doesn't actually work
Uważam, że twój kod jest nieprawidłowy; to będzie w rzeczywistości badania dla trzech wartości:
nil
,false
, i zero. Dzieje się tak, ponieważ!val
wyrażenie jest prawdziwe dla wszystkich wartości, które są fałszywe, czyli w Rubimnil
ifalse
.Najlepsze, co mogę teraz wymyślić, to
if val == nil || val == 0 # do stuff end
Co oczywiście nie jest zbyt sprytne, ale (bardzo) jasne.
źródło
Moje rozwiązanie również korzysta z zawężeń bez warunkowych.
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
źródło
Railsy robią to za pomocą metod zapytań o atrybuty, gdzie oprócz wartości false i nil wartości 0 i „” również dają wartość false.
if (model.attribute?) # => false if attribute is 0 and model is an ActiveRecord::Base derivation
Ma jednak swoich krytyków. http://www.joegrossberg.com/archives/002995.html
źródło
#attribute
, bo nie mogę znaleźć czegoś takiego.Aby być tak idiomatycznym, jak to tylko możliwe, zasugerowałbym to.
if val.nil? or val == 0 # Do something end
Dlatego:
źródło
Krótkie i jasne
[0, nil].include?(val)
źródło
val.in? [0,nil]
Powinien być najkrótszy i najlepszy sposób
if val&.>(0) # do something end
Ponieważ
val&.>(0)
zwraca nil, gdy val jest nil, ponieważ> w zasadzie jest także metodą, nil równe jest fałszowi w ruby. Zwraca fałsz, kiedyval == 0
.źródło
Radzę sobie z tym, definiując „jest”? metodę, którą mogę następnie wdrożyć w różny sposób na różnych klasach. Więc w przypadku tablicy „jest?” oznacza „rozmiar> 0”; dla Fixnum oznacza „self! = 0”; w przypadku String oznacza to "self! = ''". NilClass oczywiście definiuje „jest?” jako po prostu zwracając zero.
źródło
Możesz użyć,
case
jeśli chcesz:case val with nil, 0 # do stuff end
Wtedy możesz użyć wszystkiego, co działa
===
, co czasami jest miłe. Lub zrób coś takiego: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
To nie jest do końca dobre OOP, ale jest bardzo elastyczne i działa. Moje
if
i tak zwykle kończą się jakocase
s.Oczywiście
Enum.any?
/Enum.include?
rodzaj też działa ... jeśli lubisz być naprawdę tajemniczy:if [0, nil].include? val #do stuff end
Oczywiście należy zdefiniować metodę lub funkcję. Lub, jeśli musisz zrobić to samo z wieloma wartościami, użyj kombinacji tych ładnych iteratorów.
źródło
Naprawdę podoba mi się
blank?
metoda Railsów do tego typu rzeczy, ale nie wrócitrue
do tego0
. Możesz więc dodać swoją metodę:def nil_zero? if respond_to?(:zero?) zero? else !self end end
I sprawdzi, czy jakaś wartość jest zerowa czy 0:
nil.nil_zero? => true 0.nil_zero? => true 10.nil_zero? => false if val.nil_zero? #... end
źródło
Zamiast małpy łatać klasę, możesz użyć udoskonaleń począwszy od Rubiego 2.1. Udoskonalenia są podobne do poprawiania małp; w związku z tym umożliwiają modyfikowanie klasy, ale modyfikacja jest ograniczona do zakresu, w którym chcesz jej użyć.
To przesada, jeśli chcesz raz to sprawdzić, ale jeśli się powtarzasz, jest to świetna alternatywa dla małpiego łatania.
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
Doprecyzowania zostały zmienione w ostatniej chwili, aby uzyskać zakres pliku. Więc wcześniejsze przykłady mogły to pokazać, co nie zadziała.
class Car using NilOrZero end
źródło
To jest bardzo zwięzłe:
if (val || 0) == 0 # Is nil, false, or zero. end
Działa tak długo, jak nie masz nic przeciwko traktowaniu
false
tego samegonil
. W projektach, nad którymi pracowałem, to rozróżnienie ma znaczenie tylko raz na jakiś czas. Przez resztę czasu osobiście wolę przeskakiwać.nil?
i mieć nieco krótszy kod.[ Aktualizacja : nie piszę już tego typu rzeczy. Działa, ale jest zbyt tajemniczy. Próbowałem naprawić swoje złe uczynki, zmieniając kilka miejsc, w których to zrobiłem.]
Nawiasem mówiąc, nie użyłem,
.zero?
ponieważ powoduje to wyjątek, jeślival
jest, powiedzmy, ciągiem. Ale.zero?
byłoby dobrze, gdybyś wiedział, że tak nie jest.źródło
[edited]
Pomyślałem, że jeślival
jest nil, to wyrażenie zwróci wartośćnil == 0
(i zwrócifalse
). Wygląda jednak na to, że faktycznie działa, chociaż nie sądzę, aby był bardzo czytelny.To daje wartość true dla zera i zera:
nil.to_s.to_d == 0
źródło
unless (val || 0).zero? # do stufff end
źródło
Inne rozwiązanie:
if val.to_i == 0 # do stuff end
źródło
"5".to_i == 5
, ale masz mniej więcej rację. Sprytne, ale tak naprawdę nie działa.val ||= 0 if val == 0 # do something here end
źródło
val
trzeba zachować wartość w ? Tą metodą przebijasz dane wejściowe i istnieją lepsze, mniej destrukcyjne sposoby sprawdzania, czy nie ma zera lub zera.