Folosesc următorul cod pentru a verifica dacă o variabilă nu este nil și nu este zero
if(discount != nil && discount != 0)
...
end
Există o modalitate mai bună de a face acest lucru?
unless discount.nil? || discount == 0 # ... end
- @yxi Dar, conform acestor orientări, nu este || opțiunea preferată în acest caz? – > .
- Folosiți ||, simbolurile sunt mai ușor de citit decât cuvintele. Oricine încearcă să citească o problemă în cuvinte înțelege aceste dureri… are sens doar după ce o scrii în formularea matematică. – > .
- Utilizarea lui „sau” este periculoasă. ‘or’ are o prezență de operator mai mică decât ‘=’, astfel încât următoarea are un comportament neașteptat: a = fals sau adevărat #a este fals după această afirmație – > .
- @xiy în prezent, ghidul recomandă să se pretindă că or și and și nu există (|| is that or && and?) – > .
- Actualul „Ghid de stil Ruby” este
The and and or keywords are banned. It's just not worth it. Always use && and || instead.
. Și este corect, din motivele lui David și Tom. – > .
40
20
71
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
Atenție la obișnuitele dezmințiri… mare putere/responsabilitate, maimuțăreala care duce spre partea întunecată etc.
ok, după ce au trecut 5 ani….
if discount.try :nonzero?
...
end
Este important de reținut că try
este definit în gemul ActiveSupport, deci nu este disponibil în ruby simplu.
- Rețineți că acesta este un specifică șinelor răspuns. Vanilla ruby nu are o funcție
try
metodă. – > . - Corect. Deși este mai mult ca ActiveSupport-specific, care este o dependență mult mai ușoară și utilizată pe scară largă decât șinele complete. Oricum, acum răspunsul lui @ndn este cel corect. – > .
- Editat pentru a utiliza navigarea sigură – > .
- Răspunsul dublează acum stackoverflow.com/a/34819818/1954610 … Cred că este util să-l lăsăm așa cum este
try
pentru a arăta opțiunea alternativă (acesta este motivul pentru care a fost votat în primul rând!), atâta timp cât este clar pentru cititor căActiveSupport
nu este vanilla ruby. – > . - S-a reținut punctul de vedere, răspunsul a fost retras. – > .
unless [nil, 0].include?(discount) # ... end
- Frumos? Da. Citibilă? Nu prea. – > .
- Mi se pare perfect lizibilă și aș prefera-o în locul unei clase noi. Bine făcut. – > .
- Abordarea cea mai rubyistă de a gestiona două condiții. – > .
Începând cu Ruby 2.3.0, puteți combina operatorul de navigare sigură (&.
) cu Numeric#nonzero?
. &.
returnează nil
dacă instanța a fost nil
și nonzero?
– dacă numărul a fost 0
:
if discount&.nonzero?
# ...
end
Sau postfix:
do_something if discount&.nonzero?
"foo"&.nonzero? # => NoMethodError: undefined method 'nonzero?' for "foo":String
…. Acest lucru nu este sigur pentru a fi utilizat pe obiecte arbitrare. – > .- @TomLord, așa cum s-a precizat în comentariul anterior, acest lucru nu a fost conceput pentru a funcționa cu obiecte arbitrare. În schimb, se referă la cazul în care aveți ceva despre care știți că ar trebui să fie un număr, dar care ar putea fi și
nil
. – > . - Aș clarifica acest fapt în răspuns, mai degrabă decât ca cineva care citește pe scurt acest lucru și nu observă avertismentul din comentarii. – > .
- @TomLord, se precizează în răspuns „
nonzero?
– dacă numărul a fost0
„. De asemenea, necesitatea de a verifica dacă un obiect complet arbitrar este0
apare extrem de rar în comparație cu cea de a verifica un număr care poate fi sau nu poate finil
. Prin urmare, acest lucru este aproape implicit. Chiar dacă cineva face cumva presupunerea contrară, va înțelege instantaneu ce se întâmplă atunci când va încerca să o execute. – > .
Ați putea face acest lucru:
if (!discount.nil? && !discount.zero?)
Ordinea este importantă aici, pentru că dacă discount
este nil
, atunci nu va avea un zero?
metodă. Evaluarea în scurtcircuit a lui Ruby ar trebui să împiedice încercarea de a evalua discount.zero?
, totuși, dacă discount
este nil
.
if (discount||0) != 0
#...
end
- Acesta este răspunsul meu preferat – > .
Puteți converti rândul gol în valoare întreagă și verificați zero?.
"".to_i.zero? => true
nil.to_i.zero? => true
- atent: 0.1.to_i == 0 – > .
if discount and discount != 0
..
end
actualizare, se va false
pentru discount = false
def is_nil_and_zero(data)
data.blank? || data == 0
end
Dacă trecem „” va returna false în timp ce blank? returnează true.Același lucru se întâmplă și în cazul în care data = falseblank? returnează true pentru nil, false, empty sau un șir de caractere albe.Deci este mai bine să folosiți metoda blank? pentru a evita și șirurile goale.
blank?
este o metodă specifică șinelor și nu este disponibilă în ruby vanilie. – > .- Aveți dreptate!!! M-am gândit că acest lucru este legat de tag-ul „ror”, așa că am postat aici. Greșeala mea. Acest lucru nu va funcționa în vanilla ruby. – > .
Puteți profita de NilClass
furnizat #to_i
care va returna zero pentru nil
valori:
unless discount.to_i.zero?
# Code here
end
Dacă discount
pot fi numere fracționare, puteți utiliza #to_f
pentru a împiedica rotunjirea numărului la zero.
- Nu este acesta același lucru cu răspunsul lui @oivoodo? – > .
- Nu funcționează pentru obiecte arbitrare.
"".to_i == "foo".to_i == "0".to_i == 0
. Metoda dvs. va face tot felul de coerciții de tip neintenționate. De asemenea, va eșua cu unNoMethodError
dacădiscount
nu răspunde lato_i
. – > .
Când ai de-a face cu un înregistrare în baza de date, îmi place să inițializez toate valorile goale cu 0, folosind ajutorul de migrare:
add_column :products, :price, :integer, default: 0
if discount.nil? || discount == 0
[do something]
end
Ați putea inițializa reducerea la 0, atâta timp cât codul dvs. este garantat să nu încerce să o folosească înainte de a fi inițializat. Asta ar elimina o verificare, presupun, nu mă pot gândi la altceva.
Prefer să folosesc o abordare mai curată :
val.to_i.zero?
val.to_i
va returna un 0
dacă val este a nil
,
după care, tot ce trebuie să facem este să verificăm dacă valoarea finală este a zero.
Da, avem o modalitate curată în ruby.
discount.to_f.zero?
Această verificare gestionează o cantitate bună de cazuri, de exemplu, reducerea poate fi zero, reducerea poate fi int 0, reducerea poate fi float 0.0, reducerea poate fi șirul „0.0”, „0”.
Soluția alternativă este să folosiți Refinements, astfel:
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
Cred că următorul lucru este suficient de bun pentru codul ruby. Nu cred că aș putea scrie un test unitar care să arate vreo diferență între acesta și original.
if discount != 0
end
- Acesta ar evalua la
true
dacă reducerea ar finil
. – > .
discount
este fals? – > Por Andrew Grimm.discount.in? [0, nil]
că cel mai curat mod posibil – > Por intmarinoreturn0.