Verificarea dacă o variabilă nu este nil și nu zero în ruby (Programare, Ruby)

hectorsq a intrebat.

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?

Comentarii

  • Probabil pentru că este o copie exactă a stackoverflow.com/questions/209495/…. –  > Por David Nehme.
  • Ce ar trebui să se facă dacă discount este fals? –  > Por Andrew Grimm.
  • Eu cred că discount.in? [0, nil] că cel mai curat mod posibil –  > Por intmarinoreturn0.
18 răspunsuri
Dejan Simic
unless discount.nil? || discount == 0
  # ...
end

Comentarii

  • @yxi Dar, conform acestor orientări, nu este || opțiunea preferată în acest caz? –  > Por Josef Engelfrost.
  • 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ă. –  > Por David Betz.
  • 40

  • 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 –  > Por Tom G.
  • 20

  • @xiy în prezent, ghidul recomandă să se pretindă că or și and și nu există (|| is that or && and?) –  > Por user3125280.
  • 71

  • 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. –  > Por Andre Figueiredo.
madlep
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.

rescrisă pe

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.

Comentarii

  • Rețineți că acesta este un specifică șinelor răspuns. Vanilla ruby nu are o funcție try metodă. –  > Por Tom Lord.
  • 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. –  > Por rescris.
  • Editat pentru a utiliza navigarea sigură –  > Por rescris.
  • 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. –  > Por Tom Lord.
  • S-a reținut punctul de vedere, răspunsul a fost retras. –  > Por rescris.
Dejan Simic
unless [nil, 0].include?(discount) 
  # ...
end

Comentarii

  • Frumos? Da. Citibilă? Nu prea. –  > Por El Ninja Trepador.
  • Mi se pare perfect lizibilă și aș prefera-o în locul unei clase noi. Bine făcut. –  > Por colincr.
  • Abordarea cea mai rubyistă de a gestiona două condiții. –  > Por Yugendran.
ndnenkov

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

Comentarii

  • "foo"&.nonzero? # => NoMethodError: undefined method 'nonzero?' for "foo":String …. Acest lucru nu este sigur pentru a fi utilizat pe obiecte arbitrare. –  > Por Tom Lord.
  • @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. –  > Por ndnenkov.
  • 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. –  > Por Tom Lord.
  • @TomLord, se precizează în răspuns nonzero? – dacă numărul a fost 0. De asemenea, necesitatea de a verifica dacă un obiect complet arbitrar este 0 apare extrem de rar în comparație cu cea de a verifica un număr care poate fi sau nu poate fi nil. 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. –  > Por ndnenkov.
Jeremy Ruten

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.

Raimonds Simanovskis
if (discount||0) != 0
  #...
end

Comentarii

  • Acesta este răspunsul meu preferat –  > Por Wilson Freitas.
oivoodoodoo

Puteți converti rândul gol în valoare întreagă și verificați zero?.

"".to_i.zero? => true
nil.to_i.zero? => true

Comentarii

  • atent: 0.1.to_i == 0 –  > Por Simon B..
rubyprince
if discount and discount != 0
  ..
end

actualizare, se va false pentru discount = false

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

Comentarii

  • blank? este o metodă specifică șinelor și nu este disponibilă în ruby vanilie. –  > Por Tom Lord.
  • 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. –  > Por Saroj.
Dave G-W

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.

Comentarii

  • Nu este acesta același lucru cu răspunsul lui @oivoodo? –  > Por Cary Swoveland.
  • 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 un NoMethodError dacă discount nu răspunde la to_i. –  > Por Tom Lord.
pastullo

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

Abhinay Reddy Keesara
if discount.nil? || discount == 0
  [do something]
end

Ed S.

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.

Ozesh

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.

NIshank

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”.

RichOrElse

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

Jeff Waltzer

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

Comentarii

  • Acesta ar evalua la true dacă reducerea ar fi nil. –  > Por Andrew Grimm.

Tags: