Bagaimana cara menulis switch
pernyataan di Ruby?
Bagaimana cara menulis switch
pernyataan di Ruby?
Jawaban:
Ruby menggunakan case
ekspresi sebagai gantinya.
case x
when 1..5
"It's between 1 and 5"
when 6
"It's 6"
when "foo", "bar"
"It's either foo or bar"
when String
"You passed a string"
else
"You gave me #{x} -- I have no idea what to do with that."
end
Ruby membandingkan objek dalam when
klausa dengan objek dalam case
klausa menggunakan ===
operator. Misalnya 1..5 === x
,, dan tidak x === 1..5
.
Ini memungkinkan when
klausa canggih seperti yang terlihat di atas. Kisaran, kelas, dan segala macam hal dapat diuji bukan hanya untuk kesetaraan.
Tidak seperti switch
pernyataan dalam banyak bahasa lain, Ruby case
tidak memiliki fall-through , jadi tidak perlu mengakhiri masing when
- masing dengan a break
. Anda juga dapat menentukan beberapa kecocokan dalam satu when
klausa seperti when "foo", "bar"
.
when
dan return
pernyataan pada baris yang sama:when "foo" then "bar"
switch
pernyataan dalam banyak bahasa lain, Ruby case
TIDAK memiliki fall-through , jadi tidak perlu mengakhiri masing when
- masing dengan a break
.
then
. Silakan juga lihat jawaban lainnya.
case...when
berperilaku agak tidak terduga ketika menangani kelas. Ini disebabkan oleh fakta bahwa ia menggunakan ===
operator.
Operator itu berfungsi seperti yang diharapkan dengan literal, tetapi tidak dengan kelas:
1 === 1 # => true
Fixnum === Fixnum # => false
Ini berarti bahwa jika Anda ingin melakukan case ... when
lebih dari satu kelas objek, ini tidak akan berfungsi:
obj = 'hello'
case obj.class
when String
print('It is a string')
when Fixnum
print('It is a number')
else
print('It is not a string or number')
end
Akan mencetak "Ini bukan string atau angka".
Untungnya, ini mudah diselesaikan. The ===
Operator telah didefinisikan sehingga mengembalikan true
jika Anda menggunakannya dengan kelas dan menyediakan sebuah instance dari kelas yang sebagai operan kedua:
Fixnum === 1 # => true
Singkatnya, kode di atas dapat diperbaiki dengan menghapus .class
:
obj = 'hello'
case obj # was case obj.class
when String
print('It is a string')
when Fixnum
print('It is a number')
else
print('It is not a string or number')
end
Saya mendapatkan masalah ini hari ini sambil mencari jawaban, dan ini adalah halaman pertama yang muncul, jadi saya pikir itu akan bermanfaat bagi orang lain dalam situasi yang sama.
.class
bagian dalam menarik untuk dicatat, terima kasih. Tentu saja, ini sepenuhnya perilaku yang sesuai (meskipun saya bisa melihat bagaimana mungkin kesalahan umum untuk berpikir yang akan mencetak It is a string
) ... Anda sedang menguji kelas dari beberapa objek yang arbitrer, bukan objek itu sendiri. Jadi, misalnya: case 'hello'.class when String then "String!" when Class then "Class!" else "Something else" end
hasil dalam: "Class!"
Ini bekerja sama untuk 1.class
, {}.class
, dll menjatuhkan .class
, kita mendapatkan "String!"
atau "Something else"
untuk berbagai nilai-nilai.
Ini dilakukan menggunakan case
di Ruby. Lihat juga " Alihkan pernyataan " di Wikipedia.
Dikutip:
case n
when 0
puts 'You typed zero'
when 1, 9
puts 'n is a perfect square'
when 2
puts 'n is a prime number'
puts 'n is an even number'
when 3, 5, 7
puts 'n is a prime number'
when 4, 6, 8
puts 'n is an even number'
else
puts 'Only single-digit numbers are allowed'
end
Contoh lain:
score = 70
result = case score
when 0..40 then "Fail"
when 41..60 then "Pass"
when 61..70 then "Pass with Merit"
when 71..100 then "Pass with Distinction"
else "Invalid Score"
end
puts result
Pada sekitar halaman 123 dari Bahasa Pemrograman Ruby (Edisi 1, O'Reilly) di Kindle saya, dikatakan then
kata kunci yang mengikuti when
klausa dapat diganti dengan baris baru atau titik koma (seperti dalam if then else
sintaksis). (Ruby 1.8 juga memungkinkan titik dua di tempatnya then
, tetapi sintaks ini tidak lagi diizinkan di Ruby 1.9.)
when (-1.0/0.0)..-1 then "Epic fail"
type = #{score}
setiap baris, saya hanya dapat menyalin apa yang Anda lakukan. Jauh lebih elegan. Saya juga menyukai one-liner yang jauh lebih baik (jika mungkin)
Untuk menambahkan lebih banyak contoh ke jawaban Chuck :
Dengan parameter:
case a
when 1
puts "Single value"
when 2, 3
puts "One of comma-separated values"
when 4..6
puts "One of 4, 5, 6"
when 7...9
puts "One of 7, 8, but not 9"
else
puts "Any other thing"
end
Tanpa parameter:
case
when b < 3
puts "Little than 3"
when b == 3
puts "Equal to 3"
when (1..10) === b
puts "Something in closed range of [1..10]"
end
Harap waspadai " Cara menulis pernyataan beralih di Ruby " yang diperingatkan kikito.
or
Banyak bahasa pemrograman, terutama yang berasal dari C, memiliki dukungan untuk apa yang disebut Switch Fallthrough . Saya sedang mencari cara terbaik untuk melakukan hal yang sama di Ruby dan berpikir itu mungkin berguna bagi orang lain:
Dalam bahasa seperti C, fallthrough biasanya terlihat seperti ini:
switch (expression) {
case 'a':
case 'b':
case 'c':
// Do something for a, b or c
break;
case 'd':
case 'e':
// Do something else for d or e
break;
}
Di Ruby, hal yang sama dapat dicapai dengan cara berikut:
case expression
when 'a', 'b', 'c'
# Do something for a, b or c
when 'd', 'e'
# Do something else for d or e
end
Ini tidak sepenuhnya setara, karena tidak mungkin untuk 'a'
mengeksekusi blok kode sebelum jatuh ke 'b'
atau 'c'
, tetapi sebagian besar saya merasa cukup mirip untuk berguna dengan cara yang sama.
Di Ruby 2.0, Anda juga dapat menggunakan lambdas dalam case
pernyataan, sebagai berikut:
is_even = ->(x) { x % 2 == 0 }
case number
when 0 then puts 'zero'
when is_even then puts 'even'
else puts 'odd'
end
Anda juga dapat membuat komparator sendiri dengan mudah menggunakan Struct dengan custom ===
Moddable = Struct.new(:n) do
def ===(numeric)
numeric % n == 0
end
end
mod4 = Moddable.new(4)
mod3 = Moddable.new(3)
case number
when mod4 then puts 'multiple of 4'
when mod3 then puts 'multiple of 3'
end
(Contoh diambil dari " Bisakah procs digunakan dengan pernyataan kasus di Ruby 2.0? ".)
Atau, dengan kelas lengkap:
class Vehicle
def ===(another_vehicle)
self.number_of_wheels == another_vehicle.number_of_wheels
end
end
four_wheeler = Vehicle.new 4
two_wheeler = Vehicle.new 2
case vehicle
when two_wheeler
puts 'two wheeler'
when four_wheeler
puts 'four wheeler'
end
(Contoh diambil dari " Bagaimana Pernyataan Kasus Ruby Bekerja Dan Apa Yang Dapat Anda Lakukan dengannya ".)
Anda dapat menggunakan ekspresi reguler, seperti menemukan jenis string:
case foo
when /^(true|false)$/
puts "Given string is boolean"
when /^[0-9]+$/
puts "Given string is integer"
when /^[0-9\.]+$/
puts "Given string is float"
else
puts "Given string is probably string"
end
Ruby case
akan menggunakan operan kesetaraan ===
untuk ini (terima kasih @JimDeville). Informasi tambahan tersedia di " Operator Ruby ". Ini juga dapat dilakukan dengan menggunakan contoh @mmdemirbas (tanpa parameter), hanya pendekatan ini yang lebih bersih untuk jenis kasus ini.
Jika Anda ingin tahu cara menggunakan kondisi ATAU dalam wadah sakelar Ruby:
Jadi, dalam sebuah case
pernyataan, a ,
sama dengan ||
dalam sebuah if
pernyataan.
case car
when 'Maruti', 'Hyundai'
# Code here
end
Lihat " Bagaimana Pernyataan Kasus Ruby Bekerja Dan Apa Yang Dapat Anda Lakukan dengannya ".
Ini disebut case
dan berfungsi seperti yang Anda harapkan, ditambah banyak hal menyenangkan lainnya ===
yang mengimplementasikan tes.
case 5
when 5
puts 'yes'
else
puts 'else'
end
Sekarang untuk bersenang-senang:
case 5 # every selector below would fire (if first)
when 3..7 # OK, this is nice
when 3,4,5,6 # also nice
when Fixnum # or
when Integer # or
when Numeric # or
when Comparable # (?!) or
when Object # (duhh) or
when Kernel # (?!) or
when BasicObject # (enough already)
...
end
Dan ternyata Anda juga dapat mengganti rantai arbitrer if / else (yaitu, bahkan jika tes tidak melibatkan variabel umum) dengan case
dengan meninggalkan case
parameter awal dan hanya menulis ekspresi di mana kecocokan pertama adalah yang Anda inginkan.
case
when x.nil?
...
when (x.match /'^fn'/)
...
when (x.include? 'substring')
...
when x.gsub('o', 'z') == 'fnzrq'
...
when Time.now.tuesday?
...
end
Ruby menggunakan case
pergantian pernyataan penulisan.
Sesuai case
dokumentasi:
Pernyataan kasus terdiri dari kondisi opsional, yang berada dalam posisi argumen
case
, dan nol atau lebihwhen
klausa.when
Klausa pertama yang cocok dengan kondisi (atau untuk mengevaluasi kebenaran Boolean, jika kondisinya nol) “menang”, dan bait kodenya dieksekusi. Nilai pernyataan kasus adalah nilaiwhen
klausa yang berhasil , ataunil
jika tidak ada klausa tersebut.Pernyataan kasus dapat diakhiri dengan
else
klausa. Setiapwhen
pernyataan dapat memiliki beberapa nilai kandidat, dipisahkan dengan koma.
Contoh:
case x
when 1,2,3
puts "1, 2, or 3"
when 10
puts "10"
else
puts "Some other number"
end
Versi lebih pendek:
case x
when 1,2,3 then puts "1, 2, or 3"
when 10 then puts "10"
else puts "Some other number"
end
Dan seperti " Pernyataan kasus Ruby - teknik-teknik canggih " menggambarkan Ruby case
;
Dapat digunakan dengan Ranges :
case 5
when (1..10)
puts "case statements match inclusion in a range"
end
## => "case statements match inclusion in a range"
Dapat digunakan dengan Regex :
case "FOOBAR"
when /BAR$/
puts "they can match regular expressions!"
end
## => "they can match regular expressions!"
Dapat digunakan dengan Procs dan Lambdas :
case 40
when -> (n) { n.to_s == "40" }
puts "lambdas!"
end
## => "lambdas"
Juga, dapat digunakan dengan kelas pertandingan Anda sendiri:
class Success
def self.===(item)
item.status >= 200 && item.status < 300
end
end
class Empty
def self.===(item)
item.response_size == 0
end
end
case http_response
when Empty
puts "response was empty"
when Success
puts "response was a success"
end
Tergantung pada kasus Anda, Anda dapat memilih untuk menggunakan metode hash.
Jika ada daftar panjang when
s dan masing-masing memiliki nilai konkret untuk dibandingkan dengan (bukan interval), akan lebih efektif untuk mendeklarasikan hash metode dan kemudian memanggil metode yang relevan dari hash seperti itu.
# Define the hash
menu = {a: :menu1, b: :menu2, c: :menu2, d: :menu3}
# Define the methods
def menu1
puts 'menu 1'
end
def menu2
puts 'menu 2'
end
def menu3
puts 'menu3'
end
# Let's say we case by selected_menu = :a
selected_menu = :a
# Then just call the relevant method from the hash
send(menu[selected_menu])
Karena switch case
selalu mengembalikan satu objek, kami dapat langsung mencetak hasilnya:
puts case a
when 0
"It's zero"
when 1
"It's one"
end
Kasus multi-nilai kapan dan tanpa nilai:
print "Enter your grade: "
grade = gets.chomp
case grade
when "A", "B"
puts 'You pretty smart!'
when "C", "D"
puts 'You pretty dumb!!'
else
puts "You can't even use a computer!"
end
Dan solusi ekspresi reguler di sini:
print "Enter a string: "
some_string = gets.chomp
case
when some_string.match(/\d/)
puts 'String has numbers'
when some_string.match(/[a-zA-Z]/)
puts 'String has letters'
else
puts 'String has no numbers or letters'
end
case some_string, when /\d/, (stuff), when /[a-zA-Z]/, (stuff), end
(di mana ,
berarti baris baru)
Anda dapat menulis case
ekspresi dengan dua cara berbeda di Ruby:
if
pernyataancase
dan setiap when
klausa dibandingkan dengan target.age = 20
case
when age >= 21
puts "display something"
when 1 == 0
puts "omg"
else
puts "default condition"
end
atau:
case params[:unknown]
when /Something/ then 'Nothing'
when /Something else/ then 'I dont know'
end
Banyak jawaban bagus tapi saya pikir saya akan menambahkan satu factoid .. Jika Anda mencoba untuk membandingkan objek (Kelas) pastikan Anda memiliki metode kapal ruang (bukan lelucon) atau mengerti bagaimana mereka dibandingkan
" Ruby Equality And Object Comparison " adalah diskusi yang baik tentang topik tersebut.
<=>
, yang digunakan untuk mengembalikan -1, 0, 1, atau nil tergantung pada apakah perbandingan mengembalikan kurang dari, sama, lebih besar dari, atau tidak sebanding masing-masing. Dokumentasi modul Sebanding Ruby menjelaskannya.
Sebagaimana dinyatakan dalam banyak jawaban di atas, ===
operator digunakan di bawah kap pernyataan case
/ when
pernyataan.
Berikut ini informasi tambahan tentang operator itu:
===
Banyak kelas bawaan Ruby, seperti String, Range, dan Regexp, menyediakan implementasi ===
operator mereka sendiri , juga dikenal sebagai "kesetaraan kasus", "triple equals" atau "threequals". Karena diimplementasikan secara berbeda di setiap kelas, ia akan berperilaku berbeda tergantung pada jenis objek yang dipanggil. Secara umum, ia mengembalikan true jika objek di sebelah kanan "milik" atau "adalah anggota" objek di sebelah kiri. Misalnya, ini dapat digunakan untuk menguji apakah suatu objek adalah turunan dari kelas (atau salah satu dari sub-kelasnya).
String === "zen" # Output: => true
Range === (1..2) # Output: => true
Array === [1,2,3] # Output: => true
Integer === 2 # Output: => true
Hasil yang sama dapat dicapai dengan metode lain yang mungkin paling cocok untuk pekerjaan itu, seperti is_a?
dan instance_of?
.
===
Ketika ===
operator dipanggil pada objek jangkauan, itu mengembalikan true jika nilai di sebelah kanan jatuh dalam rentang di sebelah kiri.
(1..4) === 3 # Output: => true
(1..4) === 2.345 # Output: => true
(1..4) === 6 # Output: => false
("a".."d") === "c" # Output: => true
("a".."d") === "e" # Output: => false
Ingat bahwa ===
operator memanggil ===
metode objek kiri. Begitu (1..4) === 3
juga dengan (1..4).=== 3
. Dengan kata lain, kelas operan kiri akan menentukan implementasi ===
metode yang akan dipanggil, sehingga posisi operan tidak dapat dipertukarkan.
===
Mengembalikan nilai true jika string di sebelah kanan cocok dengan ekspresi reguler di sebelah kiri.
/zen/ === "practice zazen today" # Output: => true
# is similar to
"practice zazen today"=~ /zen/
Satu-satunya perbedaan yang relevan antara dua contoh di atas adalah bahwa, ketika ada kecocokan, ===
mengembalikan true dan =~
mengembalikan integer, yang merupakan nilai sebenarnya di Ruby. Kami akan segera kembali ke sini.
puts "Recommend me a language to learn?"
input = gets.chomp.downcase.to_s
case input
when 'ruby'
puts "Learn Ruby"
when 'python'
puts "Learn Python"
when 'java'
puts "Learn Java"
when 'php'
puts "Learn PHP"
else
"Go to Sleep!"
end
$age = 5
case $age
when 0 .. 2
puts "baby"
when 3 .. 6
puts "little child"
when 7 .. 12
puts "child"
when 13 .. 18
puts "youth"
else
puts "adult"
end
Lihat " Ruby - if ... else, case, kecuali " untuk informasi lebih lanjut.
Saya sudah mulai menggunakan:
a = "secondcase"
var_name = case a
when "firstcase" then "foo"
when "secondcase" then "bar"
end
puts var_name
>> "bar"
Ini membantu kode ringkas dalam beberapa kasus.
Hash
, daripada case
pernyataan.
Tidak ada dukungan untuk ekspresi reguler di lingkungan Anda? Misalnya Editor Skrip Shopify (April, 2018):
[Kesalahan]: RegExp konstan tidak diinisialisasi
Solusi yang mengikuti kombinasi metode yang sebelumnya telah dibahas di sini dan di sini :
code = '!ADD-SUPER-BONUS!'
class StrContains
def self.===(item)
item.include? 'SUPER' or item.include? 'MEGA' or\
item.include? 'MINI' or item.include? 'UBER'
end
end
case code.upcase
when '12345PROMO', 'CODE-007', StrContains
puts "Code #{code} is a discount code!"
when '!ADD-BONUS!'
puts 'This is a bonus code!'
else
puts 'Sorry, we can\'t do anything with the code you added...'
end
Saya menggunakan or
s dalam pernyataan metode kelas karena ||
memiliki prioritas lebih tinggi daripada
.include?
. Jika Anda seorang ruby-nazi , tolong bayangkan saya menggunakan ini (item.include? 'A') || ...
sebagai gantinya. tes repl.it.
Sangat penting untuk menekankan koma ( ,
) dalam when
klausa. Ini bertindak sebagai ||
sebuah if
pernyataan, yaitu, hal itu merupakan OR perbandingan dan bukan DAN perbandingan antara ekspresi dibatasi dari when
klausa. Lihat pernyataan kasus berikut:
x = 3
case x
when 3, x < 2 then 'apple'
when 3, x > 2 then 'orange'
end
=> "apple"
x
tidak kurang dari 2, namun nilai kembalinya adalah "apple"
. Mengapa? Karena x
3 dan sejak ',`` acts as an
|| , it did not bother to evaluate the expression
x <2 '.
Anda mungkin berpikir bahwa untuk melakukan DAN , Anda dapat melakukan sesuatu seperti ini di bawah, tetapi tidak berhasil:
case x
when (3 && x < 2) then 'apple'
when (3 && x > 2) then 'orange'
end
=> nil
Itu tidak bekerja karena (3 && x > 2)
mengevaluasi ke true, dan Ruby mengambil nilai True dan membandingkannya x
dengan ===
, yang tidak benar, karena x
adalah 3.
Untuk melakukan &&
perbandingan, Anda harus memperlakukan case
seperti if
/ else
blok:
case
when x == 3 && x < 2 then 'apple'
when x == 3 && x > 2 then 'orange'
end
Dalam buku Bahasa Pemrograman Ruby, Matz mengatakan formulir terakhir ini adalah formulir sederhana (dan jarang digunakan), yang tidak lebih dari sintaks alternatif untuk if
/ elsif
/ else
. Namun, apakah itu jarang digunakan atau tidak, saya tidak melihat cara lain untuk melampirkan banyak &&
ekspresi untuk when
klausa yang diberikan .
if...elsif
? Tampaknya Anda mencoba mencampur pernyataan kasus dan kondisi. Mengapa? Masukkan saja kondisional ke dalam blok when, mis. when 3; ( x < 2 ) ? 'apple' : 'orange'
Kita dapat menulis pernyataan beralih untuk berbagai kondisi.
Sebagai contoh,
x = 22
CASE x
WHEN 0..14 THEN puts "#{x} is less than 15"
WHEN 15 THEN puts "#{x} equals 15"
WHEN 15 THEN puts "#{x} equals 15"
WHEN 15..20 THEN puts "#{x} is greater than 15"
ELSE puts "Not in the range, value #{x} "
END
case
, when
, end
) Adalah case-sensitive dan tidak bisa huruf besar seperti ini.
NoMethodError (undefined method
CASE 'untuk main: Object) `. Seperti yang dikatakan @ sondra.kinsey, Anda tidak dapat menggunakan huruf besar. Ruby akan berpikir itu adalah KONSTAN.
The case
Operator pernyataan seperti switch
dalam bahasa-bahasa lain.
Ini adalah sintaks dari switch...case
dalam C:
switch (expression)
{
case constant1:
// statements
break;
case constant2:
// statements
break;
.
.
.
default:
// default statements
}
Ini adalah sintaks case...when
dalam Ruby:
case expression
when constant1, constant2 #Each when statement can have multiple candidate values, separated by commas.
# statements
next # is like continue in other languages
when constant3
# statements
exit # exit is like break in other languages
.
.
.
else
# statements
end
Sebagai contoh:
x = 10
case x
when 1,2,3
puts "1, 2, or 3"
exit
when 10
puts "10" # it will stop here and execute that line
exit # then it'll exit
else
puts "Some other number"
end
Untuk informasi lebih lanjut, lihat case
dokumentasi.