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?


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

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.


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.


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

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?

"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


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.


11

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

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

ostrożnie: 0.1.to_i == 0
Simon B.

3
if discount and discount != 0
  ..
end

aktualizacja, to będzie falsedladiscount = false


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.


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.


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

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.



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 .


-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

-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

8
Oceniłoby, trueczy rabat byłby nil.
Andrew Grimm,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.