Sprawdzanie, czy zmienna nie ma wartości zero ani zero w rubinie

271

Korzystam z następującego kodu, aby sprawdzić, czy zmienna nie ma wartości zero ani zero

if(discount != nil && discount != 0) 
  ...
end

Czy jest na to lepszy sposób?

hektorsq
źródło
1
Prawdopodobnie dlatego, że jest dokładną kopią stackoverflow.com/questions/209495/... .
David Nehme
1
Co powinien zrobić, jeśli discountjest fałszywy?
Andrew Grimm,
1
Myślę, że discount.in? [0, nil]czystszy sposób jest możliwy
intmarinoreturn0

Odpowiedzi:

428
chyba że rabat. zero? || rabat == 0
  # ...
koniec
Dejan Simic
źródło
31
Użyj „lub” zamiast ||
Orion Edwards,
93
@ orion-edwards, dlaczego?
NARKOZ,
39
Używanie „lub” jest niebezpieczne. „lub” ma niższą presendencję operatora niż „=”, więc następujące zachowanie jest nieoczekiwane: a = fałsz lub prawda #a jest fałszem po tym stwierdzeniu
Tom G
20
@xiy obecnie przewodnik zaleca udawanie lub i i nie istnieje (|| czy to lub && i?)
user3125280,
67
Obecne „Przewodnik po stylu Ruby” The and and or keywords are banned. It's just not worth it. Always use && and || instead.. I słusznie, z powodów Davida i Toma.
Andre Figueiredo
40
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

Uważaj na zwykłe zrzeczenia się odpowiedzialności ... wielką moc / odpowiedzialność, łatanie małp prowadzące do ciemnej strony itp.

madlep
źródło
28

ok, po 5 latach minęło ....

if discount.try :nonzero?
  ...
end

Należy zauważyć, że tryjest zdefiniowany w klejnocie ActiveSupport, więc nie jest dostępny w zwykłym rubinie.

przepisane
źródło
7
Zauważ, że jest to odpowiedź specyficzna dla torów . Rubin waniliowy nie ma trymetody.
Tom Lord,
Poprawny. Chociaż jest bardziej podobny do ActiveSupport, która jest znacznie lżejszą i szeroko stosowaną zależnością niż pełne szyny. W każdym razie odpowiedź @ ndn jest właściwa.
przepisany
Edytowano, aby korzystać z bezpiecznej nawigacji
przepisano
1
Odpowiedź duplikuje teraz stackoverflow.com/a/34819818/1954610 ... Myślę, że pozostawienie jej ma wartość, ponieważ trypokazuje alternatywną opcję (dlatego właśnie została oceniona!), O ile jest to jasne czytelnik, który ActiveSupportnie jest waniliowym rubinem.
Tom Lord
Punkt wzięty, odpowiedź cofnięta.
przepisany
27
chyba że [zero, 0] .include? (rabat) 
  # ...
koniec
Dejan Simic
źródło
13
Piękny? Tak. Czytelny? Nie całkiem.
El Ninja Trepador
1
Uważam to za doskonale czytelne i wolałbym to niż nową klasę. Dobra robota.
colincr
Najbardziej rubinowe podejście do radzenia sobie z dwoma warunkami.
Yugendran,
23

Począwszy od Ruby 2.3.0, możesz łączyć bezpieczny operator nawigacji ( &.) z Numeric#nonzero?. &.zwraca, niljeśli instancja była nili nonzero?- jeśli liczba była 0:

if discount&.nonzero?
  # ...
end

Lub postfiks:

do_something if discount&.nonzero?
ndnenkov
źródło
"foo"&.nonzero? # => NoMethodError: undefined method 'nonzero?' for "foo":String.... Nie można bezpiecznie używać na dowolnych obiektach.
Tom Lord,
2
@TomLord, jak stwierdzono w poprzednim komentarzu, nie było przeznaczone do pracy z dowolnymi obiektami. Zamiast tego chodzi o przypadek, gdy masz coś, o czym wiesz, że powinna to być liczba, ale może też być nil.
ndnenkov
Wyjaśniłbym ten fakt w odpowiedzi, a nie ktoś przeczytał to i nie zauważył wyłączenia odpowiedzialności w komentarzach.
Tom Lord,
@TomLord, jest to określone w odpowiedzi nonzero?- jeśli liczba była 0 . Konieczność sprawdzenia, czy powstaje całkowicie dowolny obiekt, 0pojawia się niezwykle rzadko w porównaniu z tym, aby sprawdzić liczbę, która może być lub nie nil. Dlatego jest to prawie dorozumiane. Nawet jeśli ktoś podejmie przeciwne założenie, natychmiast zrozumie, co się dzieje, gdy spróbuje to wykonać.
ndnenkov
17
if (discount||0) != 0
  #...
end
Raimonds Simanovskis
źródło
To moja ulubiona odpowiedź
Wilson Freitas,
15

Możesz to zrobić:

if (!discount.nil? && !discount.zero?)

Kolejność jest tutaj ważna, ponieważ jeśli discounttak nil, to nie będzie miała zero?metody. Ocena zwarciowa Ruby powinna jednak uniemożliwić jej ocenę discount.zero?, jeśli tak discountjest nil.

Jeremy Ruten
źródło
11

Możesz przekonwertować pusty wiersz na wartość całkowitą i sprawdzić zero ?.

"".to_i.zero? => true
nil.to_i.zero? => true
oivoodoo
źródło
ostrożnie: 0.1.to_i == 0
Simon B.
3
if discount and discount != 0
  ..
end

aktualizacja, to będzie falsedladiscount = false

rubyprince
źródło
2

Możesz skorzystać z NilClasspodanej #to_imetody, która zwróci zero dla nilwartości:

unless discount.to_i.zero?
  # Code here
end

Jeśli discountmogą być liczbami ułamkowymi, możesz #to_fzamiast tego użyć , aby zapobiec zaokrągleniu liczby do zera.

Dave GW
źródło
Czy to nie to samo, co odpowiedź @ oivoodo?
Cary Swoveland
Nie działa dla dowolnych obiektów . "".to_i == "foo".to_i == "0".to_i == 0. Twoja metoda spowoduje wszelkiego rodzaju niezamierzone koercje typu. Nie powiedzie się również, NoMethodErrorjeśli discountnie zareaguje to_i.
Tom Lord,
2
def is_nil_and_zero(data)
     data.blank? || data == 0 
end  

Jeśli miniemy „”, zwróci wartość false, a puste? zwraca true. To samo dzieje się, gdy data = false puste? zwraca true dla ciągu zerowego, false, pustego lub łańcucha spacji. Więc lepiej użyć pustego? metoda, aby uniknąć również pustego łańcucha.

Saroj
źródło
1
blank?jest metodą specyficzną dla szyn i nie jest dostępna w rubinach waniliowych.
Tom Lord
Masz rację!! Myślałem, że jest to związane z tak opublikowanym tutaj tagiem „ror”. Mój błąd. To nie zadziała w rubinowym waniliowym.
Saroj
1

Podczas pracy z rekordem bazy danych lubię inicjować wszystkie puste wartości za pomocą 0, korzystając z pomocnika migracji:

add_column :products, :price, :integer, default: 0
pastullo
źródło
0

Możesz zainicjować zniżkę do 0, o ile Twój kod gwarantuje, że nie spróbujesz jej użyć przed zainicjowaniem. To usunęłoby jeden czek, jak sądzę, nie mogę myśleć o niczym innym.

Ed S.
źródło
0
if discount.nil? || discount == 0
  [do something]
end
Abhinay Reddy Keesara
źródło
0

Wolę stosować bardziej czyste podejście:

val.to_i.zero?

val.to_izwróci a 0jeśli val jest anil ,

potem wszystko, co musimy zrobić, to sprawdzić, czy ostateczna wartość to zero .

Ozesh
źródło
-1

Alternatywnym rozwiązaniem jest użycie udoskonaleń, takich jak:

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
RichOrElse
źródło
-7

Uważam, że następujące elementy są wystarczająco dobre dla kodu ruby. Nie sądzę, bym mógł napisać test jednostkowy, który pokazuje jakąkolwiek różnicę między tym a oryginałem.

if discount != 0
end
Jeff Waltzer
źródło
8
Oceniłoby, trueczy rabat byłby nil.
Andrew Grimm,