Як написати switch
заяву в Ruby?
Як написати switch
заяву в Ruby?
Відповіді:
Рубі замість цього використовує case
вираз .
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 порівнює об’єкт у when
пропозиції з об'єктом у case
пункті за допомогою ===
оператора. Наприклад 1..5 === x
, і ні x === 1..5
.
Це дозволяє скласти складні when
пропозиції, як видно вище. Діапазони, класи та всілякі речі можуть бути перевірені, а не просто рівність.
На відміну від switch
висловлювань на багатьох інших мовах, у Ruby's case
немає прохідних даних , тому немає необхідності закінчувати кожну when
з а break
. Ви також можете вказати кілька збігів у одному when
пункті, як when "foo", "bar"
.
when
та return
заяву в той самий рядок:when "foo" then "bar"
then
. Будь ласка, дивіться також інші відповіді.
case...when
поводиться трохи несподівано при обробці занять. Це пов’язано з тим, що ним користується ===
оператор.
Цей оператор працює, як очікувалося, з літералами, але не з класами:
1 === 1 # => true
Fixnum === Fixnum # => false
Це означає, що якщо ви хочете зробити case ... when
над класом об'єкта, це не вийде:
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
Буде надруковано "Це не рядок або число".
На щастя, це легко вирішити. ===
Оператор був визначений так , що він повертається , true
якщо ви використовуєте його з класом і поставити екземпляр цього класу в якості другого операнда:
Fixnum === 1 # => true
Коротше кажучи, код вище можна виправити, видаливши .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
Я сьогодні потрапив на цю проблему, шукаючи відповіді, і це була перша сторінка, що з’явилася, тому я зрозумів, що це буде корисно іншим у моїй самій ситуації.
.class
участь у цьому цікаво відзначити, дякую. Звичайно, це цілком відповідна поведінка (хоча я міг бачити, як це може бути звичайною помилкою думати, що це надрукує It is a string
) ... ви тестуєте клас якогось довільного об'єкта, а не самого об'єкта. Так, наприклад: case 'hello'.class when String then "String!" when Class then "Class!" else "Something else" end
призводить до: "Class!"
Це працює так само 1.class
, {}.class
і т. Д. Відкидаючи .class
, ми отримуємо "String!"
або "Something else"
для цих різних значень.
Це робиться за допомогою case
в Ruby. Також дивіться " Переключення заяви " у Вікіпедії.
Цитується:
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
Ще один приклад:
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
На сторінці 123 на мові програмування Ruby (1-е видання, O'Reilly) на моєму Kindle написано, що then
ключове слово, що слідує за when
пунктами, може бути замінено на новий рядок або крапку з комою (як у if then else
синтаксисі). (Ruby 1.8 також дозволяє двокрапку замість then
, але цей синтаксис більше не дозволений у Ruby 1.9.)
when (-1.0/0.0)..-1 then "Epic fail"
type = #{score}
кожен рядок, я можу просто скопіювати те, що ви зробили. Набагато елегантніше мені також подобаються однолінійки набагато краще (якщо можливо)
Щоб додати більше прикладів до відповіді Чака :
З параметром:
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
Без параметра:
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
Будь ласка, пам’ятайте про те, як написати заяву про перемикання в Ruby, про яку попереджає кікіто.
or
Багато мов програмування, особливо ті, що походять від C, підтримують так званий Switch Fallthrough . Я шукав найкращий спосіб зробити те ж саме в Ruby і думав, що це може бути корисно іншим:
На мовах, подібних С, прорив зазвичай виглядає так:
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;
}
У Ruby цього можна досягти наступним чином:
case expression
when 'a', 'b', 'c'
# Do something for a, b or c
when 'd', 'e'
# Do something else for d or e
end
Це не є рівнозначним, тому що неможливо дозволити 'a'
виконувати блок коду перед тим, як потрапити на 'b'
або 'c'
, але, здебільшого, я вважаю, що це досить схоже, щоб бути корисним таким же чином.
У Ruby 2.0 ви також можете використовувати лямбдати у case
висловлюваннях:
is_even = ->(x) { x % 2 == 0 }
case number
when 0 then puts 'zero'
when is_even then puts 'even'
else puts 'odd'
end
Ви також можете легко створити власні компаратори, використовуючи Struct із користувачем ===
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
(Приклад взято з " Чи можна використовувати програми з операторами справи в Ruby 2.0? ".)
Або з повним класом:
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
(Приклад взятий із " Як працює випадок із справою Рубі і що з цим можна зробити ".)
Ви можете використовувати регулярні вирази, такі як пошук типу рядка:
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
Рубі case
використає ===
для цього операнд рівності (спасибі @JimDeville). Додаткову інформацію можна отримати у " Рубінових операторів ". Це також можна зробити, використовуючи приклад @mmdemirbas (без параметра), лише такий підхід є більш чистим для цих типів випадків.
Якщо ви прагнете знати, як використовувати умову АБО у випадку переключення Ruby:
Отже, у case
викладі а ,
є еквівалентом ||
у if
твердженні.
case car
when 'Maruti', 'Hyundai'
# Code here
end
Див. " Як працює випадок із справою" Рубі "та що з цим можна зробити ".
Це називається, case
і він працює так, як ви очікували, плюс ще багато веселощів, люб'язність ===
яких реалізує тести.
case 5
when 5
puts 'yes'
else
puts 'else'
end
Тепер для веселощів:
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
І виявляється, ви також можете замінити довільний ланцюг if / else (тобто навіть якщо тести не включають загальну змінну) case
на, виключивши початковий case
параметр і просто записавши вирази, де перший збіг - це те, що ви хочете.
case
when x.nil?
...
when (x.match /'^fn'/)
...
when (x.include? 'substring')
...
when x.gsub('o', 'z') == 'fnzrq'
...
when Time.now.tuesday?
...
end
Ruby використовує case
для написання операторів переключення.
Відповідно до case
документації:
Заяви справи складаються з необов'язкової умови, яка перебуває в позиції аргументу
case
та нульових або більшеwhen
пропозицій. Першийwhen
пункт, який відповідає умові (або для оцінки булевої істини, якщо умова є нульовою), "виграє", і його строфа коду виконується. Значення твердження справи - це значення успішноїwhen
пропозиції, абоnil
якщо такого немає.Заява справи може закінчуватися
else
пунктом. Коженwhen
вислів може мати декілька значень кандидата, розділених комами.
Приклад:
case x
when 1,2,3
puts "1, 2, or 3"
when 10
puts "10"
else
puts "Some other number"
end
Коротша версія:
case x
when 1,2,3 then puts "1, 2, or 3"
when 10 then puts "10"
else puts "Some other number"
end
І як " твердження справи Рубі - передові методики " описує Рубі case
;
Можна використовувати з діапазонами :
case 5
when (1..10)
puts "case statements match inclusion in a range"
end
## => "case statements match inclusion in a range"
Можна використовувати з Regex :
case "FOOBAR"
when /BAR$/
puts "they can match regular expressions!"
end
## => "they can match regular expressions!"
Можна використовувати з програмами та лямбдами :
case 40
when -> (n) { n.to_s == "40" }
puts "lambdas!"
end
## => "lambdas"
Також можна використовувати з власними класами матчів:
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
Залежно від вашого випадку, ви можете скористатися хеш-методами.
Якщо існує довгий список when
s і кожен з них має конкретне значення для порівняння (не інтервал), то ефективніше буде оголосити хеш методів, а потім викликати відповідний метод із такого хеша.
# 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])
Оскільки switch case
завжди повертається один об'єкт, ми можемо безпосередньо надрукувати його результат:
puts case a
when 0
"It's zero"
when 1
"It's one"
end
Багатозначне значення, коли і без значення:
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
І рішення регулярного вираження тут:
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
(де ,
означає новий рядок)
Ви можете писати case
вирази двома різними способами в Ruby:
if
твердженьcase
а кожен when
пункт порівнюється з цільовим.age = 20
case
when age >= 21
puts "display something"
when 1 == 0
puts "omg"
else
puts "default condition"
end
або:
case params[:unknown]
when /Something/ then 'Nothing'
when /Something else/ then 'I dont know'
end
Дуже багато чудових відповідей, але я подумав, що я додам один фактоїд. Якщо ви намагаєтеся порівняти об'єкти (Класи), переконайтеся, що у вас є метод космічного корабля (не на жарт) або зрозумійте, як їх порівнюють
" Рубійна рівність та порівняння об'єктів " - це хороша дискусія з цієї теми.
<=>
, який використовується для повернення -1, 0, 1 або нуля, залежно від того, повернення порівняно менше, рівне, більше, або не порівнянне. Порівнянна документація модуля Ruby пояснює це.
Як зазначено у багатьох вищезазначених відповідях, ===
оператор використовується під капотом on case
/ when
инструкції.
Ось додаткова інформація про цього оператора:
===
Багато вбудованих класів Ruby, такі як String, Range та Regexp, забезпечують власні реалізації ===
оператора, також відомі як "case-рівність", "потрійні рівні" або "threequals". Оскільки він реалізується по-різному в кожному класі, він буде поводитися по-різному в залежності від типу об'єкта, на який він був викликаний. Як правило, він повертає істину, якщо об’єкт праворуч "належить" або "є членом" об'єкта зліва. Наприклад, з його допомогою можна перевірити, чи об’єкт є екземпляром класу (або одним із його підкласів).
String === "zen" # Output: => true
Range === (1..2) # Output: => true
Array === [1,2,3] # Output: => true
Integer === 2 # Output: => true
Такого ж результату можна досягти і з іншими методами, які, ймовірно, найкраще підходять для роботи, наприклад, is_a?
та instance_of?
.
===
Коли ===
оператор викликається об'єктом діапазону, він повертає значення true, якщо значення праворуч падає в діапазон зліва.
(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
Пам'ятайте, що ===
оператор викликає ===
метод лівого об’єкта. Так що (1..4) === 3
еквівалентно (1..4).=== 3
. Іншими словами, клас лівого операнда визначатиме, яка реалізація ===
методу буде називатися, тому позиції операндів не є взаємозамінними.
===
Повертає значення true, якщо рядок праворуч відповідає регулярному виразу зліва.
/zen/ === "practice zazen today" # Output: => true
# is similar to
"practice zazen today"=~ /zen/
Єдина відповідна відмінність між двома наведеними вище прикладами полягає в тому, що, коли є збіг, ===
повертається true та =~
повертається ціле число, яке є тривале значення в Ruby. Ми повернемося до цього незабаром.
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
Для отримання додаткової інформації див. " Ruby - якщо ... інше, випадок, якщо не ".
Я почав використовувати:
a = "secondcase"
var_name = case a
when "firstcase" then "foo"
when "secondcase" then "bar"
end
puts var_name
>> "bar"
Це допомагає компактному коду в деяких випадках.
Hash
, а не case
виписку.
Немає підтримки регулярних виразів у вашому оточенні? Наприклад, редактор сценаріїв Shopify (квітень 2018 р.):
[Помилка]: неініціалізована константа RegExp
Вирішення за комбінацією методів, уже розглянутих тут і тут :
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
Я використовував or
s в операторі методу class, оскільки ||
має більшу перевагу ніж
.include?
. Якщо ви рубін-нацист , будь ласка, уявіть, що я використовував це (item.include? 'A') || ...
замість цього. тест repl.it
Надзвичайно важливо підкреслити коми ( ,
) у when
пункті. Він діє як ||
з if
заяви, тобто, він робить або порівняння і не І порівняння між роздільниками виразів when
пункту. Дивіться таку заяву справи:
x = 3
case x
when 3, x < 2 then 'apple'
when 3, x > 2 then 'orange'
end
=> "apple"
x
не менше 2, але повертається значення "apple"
. Чому? Тому що x
було 3, а з ',`` acts as an
|| , it did not bother to evaluate the expression
х <2 '.
Ви можете подумати, що для виконання І , ви можете зробити щось подібне нижче, але це не працює:
case x
when (3 && x < 2) then 'apple'
when (3 && x > 2) then 'orange'
end
=> nil
Це не працює, оскільки (3 && x > 2)
оцінюється як істинне, і Рубі приймає значення True і порівнює його x
з ===
, що не відповідає дійсності, оскільки x
це 3.
Для &&
порівняння вам доведеться ставитися case
як до if
/ else
block:
case
when x == 3 && x < 2 then 'apple'
when x == 3 && x > 2 then 'orange'
end
В Рубі Мова програмування книги, маци кажуть , що ця остання форма є простою (і рідко використовується) форма, яка є не більше ніж альтернативний синтаксис if
/ elsif
/ else
. Однак, нечасто він використовується чи ні, я не бачу іншого способу приєднання декількох &&
виразів до даного when
пункту.
if...elsif
? Здається, ви намагаєтесь змішати випадок справи та умову. Чому? Просто поставте умовне всередину блок коли, наприклад. when 3; ( x < 2 ) ? 'apple' : 'orange'
Ми можемо написати оператор переключення для декількох умов.
Наприклад,
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
) Чутливі до регістру і не може бути в верхньому регістрі , як це.
NoMethodError (undefined method
СЛУЧАЙ "для основного: Об'єкт)`. Як сказав @ sondra.kinsey, ви не можете використовувати великі регістри. Рубі подумає, що це КОНСТАНТ.
case
Оператор оператор, як і switch
в інших мовах.
Це синтаксис switch...case
в C:
switch (expression)
{
case constant1:
// statements
break;
case constant2:
// statements
break;
.
.
.
default:
// default statements
}
Це синтаксис 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
Наприклад:
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
Для отримання додаткової інформації див case
документацію.