Memeriksa apakah suatu variabel tidak nol dan tidak nol dalam ruby


271

Saya menggunakan kode berikut untuk memeriksa apakah suatu variabel tidak nil dan bukan nol

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

Apakah ada cara yang lebih baik untuk melakukan ini?


1
Mungkin karena ini adalah salinan tepat dari stackoverflow.com/questions/209495/… .
David Nehme

1
Apa yang harus dilakukan jika discountitu salah?
Andrew Grimm

1
Saya pikir discount.in? [0, nil]cara bersih mungkin
intmarinoreturn0

Jawaban:


428
kecuali diskon. || diskon == 0
  # ...
akhir

31
Gunakan 'atau' sebagai ganti ||
Orion Edwards

93
@ orion-edwards kenapa?
NARKOZ

39
Menggunakan 'atau' berbahaya. 'atau' memiliki tingkat kehadiran operator yang lebih rendah daripada '=', jadi berikut ini memiliki perilaku yang tidak terduga: a = salah atau benar #a salah setelah pernyataan ini
Tom G

20
@Yyy saat ini panduan merekomendasikan berpura-pura atau dan dan tidak ada (|| apakah itu & && dan?)
user3125280

67
Stand "Ruby Style Guide" saat ini berdiri The and and or keywords are banned. It's just not worth it. Always use && and || instead.. Dan itu benar, untuk alasan David dan Tom.
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

Waspadalah terhadap penafian biasa ... kekuatan besar / tanggung jawab, tambalan monyet mengarah ke sisi gelap dll.


28

ok, setelah 5 tahun berlalu ....

if discount.try :nonzero?
  ...
end

Penting untuk dicatat yang trydidefinisikan dalam permata ActiveSupport, sehingga tidak tersedia di ruby ​​biasa.


7
Perhatikan bahwa ini adalah jawaban khusus rel . Vanila ruby ​​tidak memiliki trymetode.
Tom Lord

Benar. Meskipun lebih seperti ActiveSupport-spesifik, yang jauh lebih ringan dan banyak digunakan daripada rel penuh. Pokoknya sekarang respon @ ndn adalah yang benar.
ditulis ulang

Diedit untuk menggunakan navigasi yang aman
ditulis ulang

1
Jawabannya sekarang menduplikasi stackoverflow.com/a/34819818/1954610 ... Saya pikir ada nilai dalam membiarkannya tryuntuk menunjukkan opsi alternatif (ini adalah alasan mengapa hal itu diputuskan di tempat pertama!), Asalkan jelas untuk pembaca yang ActiveSupportbukan ruby ​​vanila.
Tom Lord

Poin diambil, jawaban bergulir kembali.
ditulis ulang

27
kecuali [nihil, 0] .termasuk? (diskon) 
  # ...
akhir

13
Cantik? Iya. Dibaca? Tidak juga.
El Ninja Trepador

1
Saya menemukan ini mudah dibaca, dan saya lebih suka itu daripada kelas baru. Sudah selesai dilakukan dengan baik.
colincr

Pendekatan paling rubi dalam menangani dua kondisi.
Yugendran

23

Dari Ruby 2.3.0 dan seterusnya, Anda dapat menggabungkan operator navigasi aman ( &.) dengan Numeric#nonzero?. &.kembali niljika turunannya adalah nildan nonzero?- jika nomornya adalah 0:

if discount&.nonzero?
  # ...
end

Atau postfix:

do_something if discount&.nonzero?

"foo"&.nonzero? # => NoMethodError: undefined method 'nonzero?' for "foo":String.... Ini tidak aman untuk digunakan pada objek yang berubah-ubah.
Tom Lord

2
@ TomLord, seperti yang dinyatakan dalam komentar sebelumnya, ini tidak dimaksudkan untuk bekerja dengan objek yang berubah-ubah. Sebaliknya itu berkaitan dengan kasus ketika Anda memiliki sesuatu yang Anda tahu harus nomor, tetapi mungkin juga nil.
ndnenkov

Saya akan menjelaskan fakta itu dalam jawabannya, daripada seseorang membaca sekilas ini dan tidak melihat penafian dalam komentar.
Tom Lord

@TomLord, dinyatakan dalam jawaban " nonzero?- jika nomor itu 0" . Juga perlu memeriksa apakah objek yang sepenuhnya arbitrer 0muncul sangat jarang dibandingkan dengan yang memeriksa nomor yang mungkin atau mungkin tidak nil. Karena itu hampir tersirat. Bahkan jika seseorang entah bagaimana membuat asumsi yang bertentangan, mereka akan langsung mengerti apa yang terjadi ketika mereka mencoba untuk menjalankannya.
ndnenkov


15

Anda bisa melakukan ini:

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

Urutannya adalah penting di sini, karena jika discountini nil, maka tidak akan memiliki zero?metode. Evaluasi hubung singkat Ruby harus mencegahnya untuk mencoba mengevaluasi discount.zero?, jika discountada nil.


11

Anda dapat mengonversi baris kosong ke nilai integer dan memeriksa nol ?.

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

hati-hati: 0.1.to_i == 0
Simon B.

3
if discount and discount != 0
  ..
end

pembaruan, itu akan falseuntukdiscount = false


2

Anda dapat memanfaatkan metode yang NilClassdisediakan #to_i, yang akan mengembalikan nol untuk nilnilai:

unless discount.to_i.zero?
  # Code here
end

Jika discountbisa berupa angka pecahan, Anda bisa menggunakan #to_f, untuk mencegah angka dibulatkan menjadi nol.


Apakah ini tidak sama dengan jawaban @ oivoodo?
Cary Swoveland

Tidak berfungsi untuk objek sewenang-wenang . "".to_i == "foo".to_i == "0".to_i == 0. Metode Anda akan membuat segala jenis paksaan tipe yang tidak diinginkan. Ini juga akan gagal dengan NoMethodErrorjika discounttidak merespons to_i.
Tom Lord

2
def is_nil_and_zero(data)
     data.blank? || data == 0 
end  

Jika kita "" lulus, itu akan mengembalikan false sedangkan kosong? mengembalikan true. Sama halnya dengan data = false kosong? mengembalikan true untuk string nil, false, kosong, atau spasi. Jadi lebih baik menggunakan blank? metode untuk menghindari string kosong juga.


1
blank?adalah metode khusus rel, dan tidak tersedia di vanila ruby.
Tom Lord

Anda benar!! Saya pikir ini terkait dengan tag "ror" yang diposting di sini. Kesalahanku. Ini tidak akan berhasil di vanila ruby.
Saroj

1

Saat berurusan dengan catatan database , saya ingin menginisialisasi semua nilai kosong dengan 0, menggunakan bantuan migrasi:

add_column :products, :price, :integer, default: 0

0

Anda dapat menginisialisasi diskon ke 0 selama kode Anda dijamin tidak akan mencoba dan menggunakannya sebelum diinisialisasi. Itu akan menghapus satu cek saya kira, saya tidak bisa memikirkan hal lain.



0

Saya lebih suka menggunakan pendekatan yang lebih bersih:

val.to_i.zero?

val.to_iakan mengembalikan 0jika val adalah nil,

setelah itu, yang perlu kita lakukan adalah memeriksa apakah nilai akhir adalah nol .


-1

Solusi alternatif adalah menggunakan Perbaikan, seperti:

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

Saya percaya yang berikut ini cukup baik untuk kode ruby. Saya tidak berpikir saya bisa menulis unit test yang menunjukkan perbedaan antara ini dan yang asli.

if discount != 0
end

8
Itu akan mengevaluasi trueapakah diskon nil.
Andrew Grimm
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.