Câu trả lời:
Ruby sử dụng casebiể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 whenmệnh đề với đối tượng trong casemệ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 whenmệ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 switchcâu trong nhiều ngôn ngữ khác, Ruby's casekhông có thông tin , vì vậy không cần kết thúc whenbằ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 whenmệnh đề như when "foo", "bar".
whenvà returntuyê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...whencư 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 ... whenlớ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ề truenế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.
.classmộ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" endkết quả trong: "Class!"này hoạt động tương tự cho 1.class, {}.classvv 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 casetrong 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 thentừ khóa theo các whenmệ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 elsecú 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 casecâ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 casesẽ 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 casetuyên bố, a ,là tương đương với ||trong một iftuyê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 casevà 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 casecách bỏ casetham 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 casecâu lệnh chuyển đổi để viết.
Theo casetà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ố
casevà không hoặc nhiềuwhenmệnh đề.whenMệ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ủawhenmệnh đề thành công hoặcnilnế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ỗiwhencâ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 whens 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 caseluô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 casebiểu thức theo hai cách khác nhau trong Ruby:
iftuyên bốcasevà mỗi whenmệ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/ whenstatement.
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) === 3là 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 casecâ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 ors 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 whenmệnh đề. Nó hoạt động như một ||của một iftuyê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 whenmệ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"
xkhô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 expressionx <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ó xvới giá trị ===không đúng, vì xlà 3.
Để làm một phép &&so sánh, bạn sẽ phải xử lý casenhư một if/ elsekhố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 whenmệ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 casenhà điều hành tuyên bố là như switchtrong các ngôn ngữ khác.
Đây là cú pháp của switch...caseC:
switch (expression)
{
case constant1:
// statements
break;
case constant2:
// statements
break;
.
.
.
default:
// default statements
}
Đây là cú pháp của case...whenRuby:
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 casetài liệu.