Pernyataan kasus dengan beberapa nilai di setiap blok 'kapan'

315

Cara terbaik yang bisa saya uraikan adalah mencari kode gagal yang saya coba sejauh ini:

case car
  when ['honda', 'acura'].include?(car)
    # code
  when 'toyota' || 'lexus'
    # code
end

Saya punya sekitar 4 atau 5 whensituasi berbeda yang harus dipicu oleh sekitar 50 nilai yang mungkin berbeda car. Apakah ada cara untuk melakukan ini dengan caseblok atau haruskah saya mencoba ifblok besar ?

Nick
sumber

Jawaban:

669

Dalam sebuah casepernyataan, a ,sama dengan ||dalam sebuah ifpernyataan.

case car
   when 'toyota', 'lexus'
      # code
end

Beberapa hal lain yang dapat Anda lakukan dengan pernyataan kasus Ruby

Charles Caldwell
sumber
1
Tautan ini memiliki ringkasan yang lebih baik dari pernyataan kasus di Ruby (dan itu termasuk contoh sintaks regexp dan splat juga).
rsenna
Aku tidak tahu mengapa, tapi situasi yang aneh ini terjadi: Ketika saya menulis ini: when "toyota", "lexus", saya mendapatkan: unexpected tSTRING_BEG, expecting keyword_do or '{' or '(' (SyntaxError). Namun, ketika saya menulis ini when "toyota","lexus":, berfungsi. Satu-satunya perbedaan adalah spasi setelah koma.
Furkan Ayhan
@FurkanAyhan Itu aneh. Saya pergi ke depan dan menguji kode hanya untuk memastikan dan itu berhasil. Dugaan saya adalah ada hal lain yang terjadi dalam kode Anda yang menjadikannya kesalahan seperti itu. Mungkinkah Anda lupa untuk menutup string di suatu tempat atau sesuatu seperti itu?
Charles Caldwell
1
baik, ini bekerja, tetapi sebagai ruby ​​fokus pada kemudahan programmer, saya bertanya-tanya mengapa tidak mendukung standar || atau 'atau'? Ini agak membingungkan
Zia Ul Rehman Mughal
2
Ruby tidak mendukung oratau di ||sini karena whenmengambil serangkaian ekspresi yang dipisahkan koma di sebelah kanannya, bukan pengidentifikasi tunggal. Karena ini, jika Anda punya when a or b, tidak jelas apakah ini harus dianggap sama dengan when a, batau when (a or b), yang terakhir mengevaluasi ekspresi a or bterlebih dahulu sebelum melemparkannya ke kapan. Ini lebih mengejutkan dan kurang mudah ditangani karena bahasa memiliki token yang mengubah perilaku berdasarkan konteks, dan kemudian Anda tidak akan dapat menggunakan orekspresi nyata di sisi kanan kapan.
Taywee
99

Anda bisa memanfaatkan "splat" ruby ​​atau sintaks yang rata.

Ini membuat whenklausa yang terlalu banyak - Anda memiliki sekitar 10 nilai untuk diuji per cabang jika saya mengerti dengan benar - sedikit lebih mudah dibaca menurut pendapat saya. Selain itu, Anda dapat mengubah nilai untuk menguji saat runtime. Sebagai contoh:

honda  = ['honda', 'acura', 'civic', 'element', 'fit', ...]
toyota = ['toyota', 'lexus', 'tercel', 'rx', 'yaris', ...]
...

if include_concept_cars
  honda += ['ev-ster', 'concept c', 'concept s', ...]
  ...
end

case car
when *toyota
  # Do something for Toyota cars
when *honda
  # Do something for Honda cars
...
end

Pendekatan umum lainnya adalah dengan menggunakan hash sebagai tabel pengiriman, dengan kunci untuk setiap nilai cardan nilai-nilai yang merupakan beberapa objek yang dapat dipanggil yang mengenkapsulasi kode yang ingin Anda jalankan.

pilcrow
sumber
Inilah yang akhirnya saya gunakan, meskipun saya merasa tidak enak menghilangkan tanda cek seseorang: D
Nick
Solusi brilian untuk whengaris panjang . Terima kasih telah berbagi.
Pistos
0

Cara lain yang baik untuk menempatkan logika Anda dalam data adalah sesuatu seperti ini:

# Initialization.
CAR_TYPES = {
  foo_type: ['honda', 'acura', 'mercedes'],
  bar_type: ['toyota', 'lexus']
  # More...
}
@type_for_name = {}
CAR_TYPES.each { |type, names| names.each { |name| @type_for_name[type] = name } }

case @type_for_name[car]
when :foo_type
  # do foo things
when :bar_type
  # do bar things
end
Hew Wolff
sumber
Saya tidak bermaksud kasar, tetapi saya kalah karena ini kurang efisien dalam waktu dan ruang. Ini juga lebih kompleks dan kurang mudah dibaca daripada dua jawaban lainnya. Apa manfaat menggunakan metode ini?
Nick
Ini menempatkan seluruh klasifikasi Anda menjadi satu objek. Anda sekarang dapat melakukan hal-hal dengan objek itu, seperti membuat serial dan mengirimkannya ke orang lain untuk menjelaskan logika Anda, atau menyimpannya dalam database dan memungkinkan orang untuk mengeditnya. (Logikanya akan segera berubah ketika model mobil baru keluar, kan?) Anda mungkin mencari "table-driven".
Hew Wolff
YAGNI ("Anda tidak akan membutuhkannya") dapat mendaftar di sini. Desain ini mengorbankan efisiensi ruang / waktu dan keterbacaan untuk skenario yang mungkin ada di masa depan tetapi belum ada. Biayanya dibayar sekarang, tetapi hadiahnya mungkin tidak pernah dapat dituai.
Nick