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?

hectorsq
sumber
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
Dejan Simic
sumber
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.

madlep
sumber
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.

ditulis ulang
sumber
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
Dejan Simic
sumber
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?
ndnenkov
sumber
"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
17
if (discount||0) != 0
  #...
end
Raimonds Simanovskis
sumber
Ini adalah jawaban favorit saya
Wilson Freitas
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.

Jeremy Ruten
sumber
11

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

"".to_i.zero? => true
nil.to_i.zero? => true
oivoodoo
sumber
hati-hati: 0.1.to_i == 0
Simon B.
3
if discount and discount != 0
  ..
end

pembaruan, itu akan falseuntukdiscount = false

rubyprince
sumber
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.

Dave GW
sumber
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.

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

Ed S.
sumber
0
if discount.nil? || discount == 0
  [do something]
end
Abhinay Reddy Keesara
sumber
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 .

Ozesh
sumber
-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
RichOrElse
sumber
-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
Jeff Waltzer
sumber
8
Itu akan mengevaluasi trueapakah diskon nil.
Andrew Grimm