Ответы:
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 case
нет провала , поэтому нет необходимости заканчивать каждое when
символом a break
. Вы также можете указать несколько совпадений в одном when
предложении, как when "foo", "bar"
.
when
and 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
и т.д. Dropping.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
Пожалуйста, имейте в виду " Как написать оператор switch в Ruby ", о котором kikito предупреждает.
or
Многие языки программирования, особенно те, что происходят от C, поддерживают так называемый Switch Fallthrough . Я искал лучший способ сделать то же самое в Ruby и подумал, что это может быть полезно для других:
В C-подобных языках падение обычно выглядит так:
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
(Пример взят из « Можно ли использовать процы с операторами case в 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
(Пример взят из статьи « Как работает оператор Ruby и что вы можете с ним сделать ».)
Вы можете использовать регулярные выражения, такие как поиск типа строки:
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
будет использовать ===
для этого операнд равенства (спасибо @JimDeville). Дополнительная информация доступна на " Рубин Операторы ". Это также можно сделать с помощью примера @mmdemirbas (без параметра), только этот подход более чист для таких случаев.
Если вы хотите знать, как использовать условие ИЛИ в случае переключения Ruby:
Таким образом, в case
утверждении a ,
является эквивалентом ||
в if
утверждении.
case car
when 'Maruti', 'Hyundai'
# Code here
end
Смотрите " Как работает Ruby Case case и что вы можете с ним сделать ".
Он называется 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
для написания операторов switch.
Согласно case
документации:
Операторы case состоят из необязательного условия, которое находится в позиции аргумента
case
, и нуля или болееwhen
предложений. Первоеwhen
предложение, которое соответствует условию (или оценивается как логическая истина, если условие имеет значение null) «выигрывает», и выполняется его кодовая часть. Значением оператора case является значение успешногоwhen
предложения, илиnil
если такого предложения нет.Оператор case может заканчиваться
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!"
Может использоваться с Procs и Lambdas :
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 или nil в зависимости от того, возвращает ли сравнение меньше, равно, больше или не сопоставимо соответственно. В документации Ruby Comparable module это объясняется.
Как указано во многих из приведенных выше ответов, ===
оператор используется под капотом на case
/when
операторов.
Вот дополнительная информация об этом операторе:
===
Многие из встроенных в Ruby классов, такие как String, Range и Regexp, предоставляют свои собственные реализации ===
оператора, также известные как «case-равенства», «тройное равенство» или «тройное равенство». Поскольку он реализован по-разному в каждом классе, он будет вести себя по-разному в зависимости от типа объекта, к которому он был вызван. Как правило, он возвращает true, если объект справа «принадлежит» или «является членом» объекта слева. Например, его можно использовать для проверки того, является ли объект экземпляром класса (или одного из его подклассов).
String === "zen" # Output: => true
Range === (1..2) # Output: => true
Array === [1,2,3] # Output: => true
Integer === 2 # Output: => true
Тот же результат может быть достигнут с помощью других методов, которые, вероятно, лучше всего подходят для работы, таких как is_a?
иinstance_of?
.
===
Когда ===
оператор вызывается для объекта диапазона, он возвращает истину, если значение справа попадает в диапазон слева.
(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 - если ... еще, case, если только " для получения дополнительной информации.
Я начал использовать:
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 в выражении метода класса, поскольку ||
имеет более высокий приоритет, чем
.include?
. Если вы рубин-нацист , пожалуйста, представьте, что я использовал это (item.include? 'A') || ...
вместо этого. Репл.ит тест.
Важно подчеркнуть запятую ( ,
) в 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 '.
Вы можете подумать, что для выполнения AND , вы можете сделать что-то вроде этого ниже, но это не работает:
case x
when (3 && x < 2) then 'apple'
when (3 && x > 2) then 'orange'
end
=> nil
Это не работает, потому что (3 && x > 2)
оценивается как true, а Ruby принимает значение True и сравнивает его x
с значением ===
, которое не соответствует истине, поскольку x
равно 3.
Чтобы сделать &&
сравнение, вам нужно рассматривать case
как if
/ else
блок:
case
when x == 3 && x < 2 then 'apple'
when x == 3 && x > 2 then 'orange'
end
В книге Ruby Programming Language Матц говорит, что эта последняя форма является простой (и редко используемой) формой, которая является не чем иным, как альтернативным синтаксисом для if
/ elsif
/ else
. Однако, используется ли это редко или нет, я не вижу другого способа присоединить несколько &&
выражений для данного when
предложения.
if...elsif
? Похоже, вы пытаетесь смешать заявление случая и условие. Почему? Просто поместите условную внутри группы При блоке, например. when 3; ( x < 2 ) ? 'apple' : 'orange'
Мы можем написать оператор switch для нескольких условий.
Например,
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
CASE 'для main: Object) `. Как сказал @ 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
Документацию.