when - ruby условные операторы




Как написать оператор switch в Ruby (14)

случай ... когда

Чтобы добавить еще несколько примеров к ответу Чака :

С параметром:

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?


Ruby использует case для написания операторов switch.

Согласно Ruby Docs :

Операторы case состоят из необязательного условия, которое находится в позиции аргумента к case , и ноль или более when клаузе. Параметр first 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

И поскольку этот блог Honeybadger описывает случай с Ruby;

Может использоваться с Ranges :

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

В зависимости от вашего случая вы можете предпочесть использовать хеш методов.

Если есть длинный список «когда», и каждый из них имеет конкретное значение для сравнения с (а не интервал), будет более эффективным объявлять хэш методов, а затем вызывать соответствующий метод из хэша, подобного этому.

# 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])

Вы можете использовать регулярные выражения, такие как поиск типа строки:

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 Ruby будет использовать операнд равенства === для этого (спасибо @JimDeville). Дополнительную информацию можно получить у « Ruby Operators ». Это также можно сделать с помощью примера @mmdemirbas (без параметра), только этот подход более чист для этих типов случаев.


Вы можете сделать это более естественным образом,

case expression
when condtion1
   function
when condition2
   function
else
   function
end


Многие языки программирования, особенно те, которые производятся от C, поддерживают так называемый « Паттинг» . Я искал лучший способ сделать то же самое в 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' , но по большей части я считаю его достаточно похожим, чтобы быть полезным таким же образом.


Многозначный случай и без значения:

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

Нет поддержки регулярных выражений в вашей среде? Например, редактор скриптов Shopify (апрель 2018 года):

[Ошибка]: неинициализированная константа RegExp

Обходной путь после комбинации методов, которые ранее были рассмотрены here и here :

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') || ... , представьте, что я использовал это (item.include? 'A') || ... (item.include? 'A') || ... вместо этого. repl.it test.


Так как switch case всегда возвращает один объект, мы можем напрямую распечатать его результат:

puts case a
     when 0
        "It's zero"
     when 1
        "It's one"
     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

Я начал использовать:

a = "secondcase"

var_name = case a
  when "firstcase" then "foo"
  when "secondcase" then "bar"
end

puts var_name
>> "bar"

В некоторых случаях это помогает компактному коду.


Вместо этого 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 .

Это позволяет использовать сложные предложения, как показано выше. Диапазоны, классы и всевозможные вещи можно тестировать, а не просто равенство.

В отличие от операторов switch на многих других языках, case Ruby не имеет fall-through , поэтому нет необходимости заканчивать каждый раз, when происходит break . Вы также можете указать несколько совпадений в одном, when предложение, например, when "foo", "bar" .






conditional