Câu trả lời:
Ruby sử dụng case
biểu thức thay thế.
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 so sánh đối tượng trong when
mệnh đề với đối tượng trong case
mệnh đề sử dụng ===
toán tử. Ví dụ 1..5 === x
, và không x === 1..5
.
Điều này cho phép các when
mệnh đề tinh vi như đã thấy ở trên. Phạm vi, lớp học và tất cả các loại điều có thể được kiểm tra thay vì chỉ bình đẳng.
Không giống như các switch
câu trong nhiều ngôn ngữ khác, Ruby's case
không có thông tin , vì vậy không cần kết thúc when
bằng các ngôn ngữ break
. Bạn cũng có thể chỉ định nhiều kết quả khớp trong một when
mệnh đề như when "foo", "bar"
.
when
và return
tuyên bố trên cùng một dòng:when "foo" then "bar"
then
. Xin vui lòng xem các câu trả lời khác.
case...when
cư xử hơi bất ngờ khi xử lý các lớp. Điều này là do thực tế là nó sử dụng ===
toán tử.
Toán tử đó hoạt động như mong đợi với nghĩa đen, nhưng không phải với các lớp:
1 === 1 # => true
Fixnum === Fixnum # => false
Điều này có nghĩa là nếu bạn muốn thực hiện một case ... when
lớp đối tượng, điều này sẽ không hoạt động:
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
Sẽ in "Nó không phải là một chuỗi hoặc số".
May mắn thay, điều này dễ dàng được giải quyết. Các ===
nhà điều hành đã được xác định để nó trả về true
nếu bạn sử dụng nó với một lớp và cung cấp một thể hiện của lớp đó như là toán hạng thứ hai:
Fixnum === 1 # => true
Nói tóm lại, đoạn mã trên có thể được sửa bằng cách xóa .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
Tôi đã gặp vấn đề này ngày hôm nay trong khi tìm kiếm một câu trả lời, và đây là trang xuất hiện đầu tiên, vì vậy tôi cho rằng nó sẽ hữu ích cho những người khác trong tình huống tương tự của tôi.
.class
một phần trong là thú vị để lưu ý, cảm ơn. Tất nhiên, đây là hành vi hoàn toàn phù hợp (mặc dù tôi có thể thấy nó có thể là một lỗi phổ biến như thế nào khi nghĩ rằng nó sẽ in It is a string
) ... bạn đang thử nghiệm lớp của một số đối tượng tùy ý, chứ không phải chính đối tượng. Vì vậy, ví dụ: case 'hello'.class when String then "String!" when Class then "Class!" else "Something else" end
kết quả trong: "Class!"
này hoạt động tương tự cho 1.class
, {}.class
vv rơi .class
, chúng tôi nhận "String!"
hoặc "Something else"
cho các giá trị khác nhau.
Nó được thực hiện bằng cách sử dụng case
trong Ruby. Cũng xem " Chuyển đổi tuyên bố " trên Wikipedia.
Trích dẫn:
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
Một vi dụ khac:
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
Trên trang 123 của Ngôn ngữ lập trình Ruby (Ấn bản đầu tiên, O'Reilly) trên Kindle của tôi, nó cho biết then
từ khóa theo các when
mệnh đề có thể được thay thế bằng một dòng mới hoặc dấu chấm phẩy (giống như trong if then else
cú pháp). (Ruby 1.8 cũng cho phép thay thế dấu hai chấm then
, nhưng cú pháp này không còn được cho phép trong Ruby 1.9.)
when (-1.0/0.0)..-1 then "Epic fail"
type = #{score}
từng dòng, tôi chỉ có thể sao chép những gì bạn đã làm. Thanh lịch hơn nhiều Tôi cũng thích những chiếc áo lót tốt hơn nhiều (nếu có thể)
Để thêm nhiều ví dụ cho câu trả lời của Chuck :
Với tham số:
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
Không có tham số:
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
Xin vui lòng, lưu ý về " Cách viết câu lệnh chuyển đổi trong Ruby " mà kikito cảnh báo.
or
Nhiều ngôn ngữ lập trình, đặc biệt là những ngôn ngữ có nguồn gốc từ C, có hỗ trợ cho cái gọi là Chuyển đổi mùa thu . Tôi đã tìm kiếm cách tốt nhất để làm điều tương tự trong Ruby và nghĩ rằng nó có thể hữu ích cho người khác:
Trong các ngôn ngữ giống như ngôn ngữ C, thông thường trông như thế này:
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;
}
Trong Ruby, điều tương tự có thể đạt được theo cách sau:
case expression
when 'a', 'b', 'c'
# Do something for a, b or c
when 'd', 'e'
# Do something else for d or e
end
Điều này không hoàn toàn tương đương, vì không thể 'a'
thực thi một khối mã trước khi chuyển sang 'b'
hoặc 'c'
, nhưng đối với hầu hết các phần tôi thấy nó đủ tương tự để có ích theo cùng một cách.
Trong Ruby 2.0, bạn cũng có thể sử dụng lambdas trong các case
câu lệnh, như sau:
is_even = ->(x) { x % 2 == 0 }
case number
when 0 then puts 'zero'
when is_even then puts 'even'
else puts 'odd'
end
Bạn cũng có thể dễ dàng tạo các bộ so sánh của riêng mình một cách dễ dàng bằng cách sử dụng Struct với một tùy chỉnh ===
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
(Ví dụ được lấy từ " Có thể sử dụng procs với các câu lệnh tình huống trong Ruby 2.0 không? ".)
Hoặc, với một lớp hoàn chỉnh:
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
(Ví dụ được lấy từ " Cách tuyên bố trường hợp Ruby hoạt động và bạn có thể làm gì với nó ".)
Bạn có thể sử dụng các biểu thức thông thường, chẳng hạn như tìm một loại chuỗi:
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's case
sẽ sử dụng toán hạng bằng ===
cho việc này (cảm ơn @JimDeville). Thông tin bổ sung có sẵn tại " Nhà khai thác Ruby ". Điều này cũng có thể được thực hiện bằng cách sử dụng ví dụ @mmdemirbas (không có tham số), chỉ có cách tiếp cận này là sạch hơn cho các loại trường hợp này.
Nếu bạn muốn biết cách sử dụng điều kiện OR trong trường hợp chuyển đổi Ruby:
Vì vậy, trong một case
tuyên bố, a ,
là tương đương với ||
trong một if
tuyên bố.
case car
when 'Maruti', 'Hyundai'
# Code here
end
Xem " Cách tuyên bố trường hợp Ruby hoạt động và những gì bạn có thể làm với nó ".
Nó được gọi case
và nó hoạt động như bạn mong đợi, cộng với nhiều thứ thú vị hơn nhờ phép ===
thực hiện các bài kiểm tra.
case 5
when 5
puts 'yes'
else
puts 'else'
end
Bây giờ cho một số niềm vui:
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
Và hóa ra, bạn cũng có thể thay thế một chuỗi if / khác tùy ý (nghĩa là ngay cả khi các bài kiểm tra không liên quan đến một biến chung) bằng case
cách bỏ case
tham số ban đầu và chỉ viết các biểu thức trong đó kết quả khớp đầu tiên là điều bạn muốn.
case
when x.nil?
...
when (x.match /'^fn'/)
...
when (x.include? 'substring')
...
when x.gsub('o', 'z') == 'fnzrq'
...
when Time.now.tuesday?
...
end
Ruby sử dụng các case
câu lệnh chuyển đổi để viết.
Theo case
tài liệu:
Các câu lệnh tình huống bao gồm một điều kiện tùy chọn, nằm ở vị trí của một đối số
case
và không hoặc nhiềuwhen
mệnh đề.when
Mệnh đề đầu tiên phù hợp với điều kiện (hoặc để đánh giá với sự thật Boolean, nếu điều kiện này là null) thì Thắng thắng, và đoạn mã của nó được thực thi. Giá trị của câu lệnh tình huống là giá trị củawhen
mệnh đề thành công hoặcnil
nếu không có mệnh đề đó.Một tuyên bố trường hợp có thể kết thúc bằng một
else
điều khoản. Mỗiwhen
câu lệnh có thể có nhiều giá trị ứng cử viên, được phân tách bằng dấu phẩy.
Thí dụ:
case x
when 1,2,3
puts "1, 2, or 3"
when 10
puts "10"
else
puts "Some other number"
end
Phiên bản ngắn hơn:
case x
when 1,2,3 then puts "1, 2, or 3"
when 10 then puts "10"
else puts "Some other number"
end
Và như " tuyên bố trường hợp của Ruby - các kỹ thuật tiên tiến " mô tả Ruby case
;
Có thể được sử dụng với Phạm vi :
case 5
when (1..10)
puts "case statements match inclusion in a range"
end
## => "case statements match inclusion in a range"
Có thể được sử dụng với Regex :
case "FOOBAR"
when /BAR$/
puts "they can match regular expressions!"
end
## => "they can match regular expressions!"
Có thể được sử dụng với Procs và Lambdas :
case 40
when -> (n) { n.to_s == "40" }
puts "lambdas!"
end
## => "lambdas"
Ngoài ra, có thể được sử dụng với các lớp đối sánh của riêng bạn:
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
Tùy thuộc vào trường hợp của bạn, bạn có thể thích sử dụng hàm băm của phương thức.
Nếu có một danh sách dài các when
s và mỗi trong số chúng có một giá trị cụ thể để so sánh với (không phải là một khoảng), sẽ hiệu quả hơn khi khai báo một hàm băm của phương thức và sau đó gọi phương thức có liên quan từ hàm băm như thế.
# 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])
Vì switch case
luôn trả về một đối tượng, chúng ta có thể in trực tiếp kết quả của nó:
puts case a
when 0
"It's zero"
when 1
"It's one"
end
Trường hợp đa giá trị khi và không có giá trị:
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
Và một giải pháp biểu thức chính quy ở đây:
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
(nơi ,
có nghĩa là dòng mới)
Bạn có thể viết case
biểu thức theo hai cách khác nhau trong Ruby:
if
tuyên bốcase
và mỗi when
mệnh đề được so sánh với mục tiêu.age = 20
case
when age >= 21
puts "display something"
when 1 == 0
puts "omg"
else
puts "default condition"
end
hoặc là:
case params[:unknown]
when /Something/ then 'Nothing'
when /Something else/ then 'I dont know'
end
Rất nhiều câu trả lời tuyệt vời nhưng tôi nghĩ rằng tôi sẽ thêm một factoid .. Nếu bạn đang cố so sánh các đối tượng (Classes), hãy đảm bảo rằng bạn có một phương thức tàu không gian (không phải là một trò đùa) hoặc hiểu cách chúng được so sánh
" Ruby Equality And So sánh đối tượng " là một cuộc thảo luận tốt về chủ đề này.
Như đã nêu trong nhiều câu trả lời ở trên, ===
toán tử được sử dụng dưới mui xe trên case
/ when
statement.
Dưới đây là thông tin bổ sung về nhà điều hành đó:
===
Nhiều lớp dựng sẵn của Ruby, như String, Range và Regapi, cung cấp các triển khai riêng của ===
toán tử, còn được gọi là "trường hợp bình đẳng", "ba bằng" hoặc "ba phần tử". Bởi vì nó được triển khai khác nhau trong mỗi lớp, nên nó sẽ hoạt động khác nhau tùy thuộc vào loại đối tượng mà nó được gọi. Nói chung, nó trả về true nếu đối tượng bên phải "thuộc về" hoặc "là thành viên của" đối tượng bên trái. Ví dụ, nó có thể được sử dụng để kiểm tra nếu một đối tượng là một thể hiện của một lớp (hoặc một trong các lớp con của nó).
String === "zen" # Output: => true
Range === (1..2) # Output: => true
Array === [1,2,3] # Output: => true
Integer === 2 # Output: => true
Kết quả tương tự có thể đạt được với các phương pháp khác có lẽ phù hợp nhất cho công việc, chẳng hạn như is_a?
và instance_of?
.
===
Khi ===
toán tử được gọi trên một đối tượng phạm vi, nó sẽ trả về true nếu giá trị bên phải nằm trong phạm vi bên trái.
(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
Hãy nhớ rằng ===
toán tử gọi ===
phương thức của đối tượng bên trái. Như vậy (1..4) === 3
là tương đương với (1..4).=== 3
. Nói cách khác, lớp của toán hạng bên trái sẽ xác định việc thực hiện ===
phương thức nào sẽ được gọi, do đó, các vị trí toán hạng không thể thay thế cho nhau.
===
Trả về true nếu chuỗi bên phải khớp với biểu thức chính quy bên trái.
/zen/ === "practice zazen today" # Output: => true
# is similar to
"practice zazen today"=~ /zen/
Sự khác biệt duy nhất có liên quan giữa hai ví dụ trên là, khi có một kết quả khớp, ===
trả về giá trị true và =~
trả về một số nguyên, đó là một giá trị trung thực trong Ruby. Chúng tôi sẽ trở lại điều này sớm.
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
Xem " Ruby - nếu ... khác, trường hợp, trừ khi " để biết thêm thông tin.
Tôi đã bắt đầu sử dụng:
a = "secondcase"
var_name = case a
when "firstcase" then "foo"
when "secondcase" then "bar"
end
puts var_name
>> "bar"
Nó giúp mã nhỏ gọn trong một số trường hợp.
Hash
, chứ không phải là một case
câu lệnh.
Không hỗ trợ cho các biểu thức thường xuyên trong môi trường của bạn? Ví dụ: Trình chỉnh sửa tập lệnh Shopify (tháng 4 năm 2018):
[Lỗi]: hằng số chưa được khởi tạo RegExp
Một cách giải quyết sau khi kết hợp các phương pháp đã được đề cập ở đây và ở đây :
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
Tôi đã sử dụng or
s trong câu lệnh phương thức lớp vì ||
có độ ưu tiên cao hơn
.include?
. Nếu bạn là một ruby-nazi , hãy tưởng tượng tôi đã sử dụng nó (item.include? 'A') || ...
để thay thế. repl.it thử nghiệm.
Điều quan trọng là nhấn mạnh dấu phẩy ( ,
) trong when
mệnh đề. Nó hoạt động như một ||
của một if
tuyên bố, có nghĩa là, nó một HOẶC so sánh và không phải là một VÀ so sánh giữa các khái niệm phân của when
mệnh đề. Xem tuyên bố trường hợp sau đây:
x = 3
case x
when 3, x < 2 then 'apple'
when 3, x > 2 then 'orange'
end
=> "apple"
x
không nhỏ hơn 2, nhưng giá trị trả về là "apple"
. Tại sao? Bởi vì x
đã 3 và kể từ ',`` acts as an
| | , it did not bother to evaluate the expression
x <2 '.
Bạn có thể nghĩ rằng để thực hiện AND , bạn có thể làm một cái gì đó như thế này bên dưới, nhưng nó không hoạt động:
case x
when (3 && x < 2) then 'apple'
when (3 && x > 2) then 'orange'
end
=> nil
Nó không hoạt động vì (3 && x > 2)
đánh giá là đúng và Ruby lấy giá trị True và so sánh nó x
với giá trị ===
không đúng, vì x
là 3.
Để làm một phép &&
so sánh, bạn sẽ phải xử lý case
như một if
/ else
khối:
case
when x == 3 && x < 2 then 'apple'
when x == 3 && x > 2 then 'orange'
end
Trong sách Ngôn ngữ lập trình Ruby, Matz nói rằng mẫu sau này là dạng đơn giản (và được sử dụng không thường xuyên), không có gì khác hơn là một cú pháp thay thế cho if
/ elsif
/ else
. Tuy nhiên, cho dù nó có được sử dụng thường xuyên hay không, tôi không thấy cách nào khác để đính kèm nhiều &&
biểu thức cho một when
mệnh đề đã cho .
if...elsif
? Có vẻ như bạn đang cố gắng trộn lẫn một tuyên bố trường hợp và một điều kiện. Tại sao? Chỉ cần đặt điều kiện bên trong khối khi, ví dụ. when 3; ( x < 2 ) ? 'apple' : 'orange'
Chúng ta có thể viết câu lệnh chuyển đổi cho nhiều điều kiện.
Ví dụ,
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
) Là trường hợp nhạy cảm và không thể viết hoa như thế này.
NoMethodError (undefined method
TRƯỜNG HỢP 'cho chính: Đối tượng) `. Như @ sondra.kinsey đã nói, bạn không thể sử dụng chữ hoa. Ruby sẽ nghĩ đó là một CONSTANT.
Các case
nhà điều hành tuyên bố là như switch
trong các ngôn ngữ khác.
Đây là cú pháp của switch...case
C:
switch (expression)
{
case constant1:
// statements
break;
case constant2:
// statements
break;
.
.
.
default:
// default statements
}
Đây là cú pháp của case...when
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
Ví dụ:
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
Để biết thêm thông tin xem case
tài liệu.