Jak napisać instrukcję switch w Ruby?

Jak napisać instrukcję switch w Ruby?

Author: Dmitry Grigoryev, 2009-06-04

21 answers

Ruby używa case wyrażenie zamiast.

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 porównuje obiekt w klauzuli when z obiektem w klauzuli case używając operatora ===. Na przykład 1..5 === x, a nie x === 1..5.

Pozwala to na wyrafinowane when klauzule, jak pokazano powyżej. Zakresy, klasy i wszelkiego rodzaju rzeczy mogą być testowane zamiast tylko równości.

W przeciwieństwie do switch w wielu innych językach, case Ruby nie posiada , więc nie ma potrzeby kończenia każdego {[2] } znakiem break. Możesz również określić wiele dopasowań w pojedynczej klauzuli when, takiej jak when "foo", "bar".

 2346
Author: Chuck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-04 09:03:49

case...when zachowuje się nieco nieoczekiwanie podczas obsługi klas. Wynika to z faktu, że używa operatora ===.

Ten operator działa zgodnie z oczekiwaniami z literałami, ale nie z klasami:

1 === 1           # => true
Fixnum === Fixnum # => false

Oznacza to, że jeśli chcesz wykonać case ... when nad klasą obiektu, to nie zadziała:

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')
end

Wydrukuje "to nie jest łańcuch".

Na szczęście jest to łatwe do rozwiązania. Operator === został zdefiniowany tak, że zwraca true, jeśli użyjesz go z klasą i podaj instancję tej klasy jako drugi operand:

Fixnum === 1 # => true

W skrócie, powyższy kod można naprawić, usuwając .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')
end

Trafiłem dziś w ten problem, szukając odpowiedzi, i to była pierwsza pojawiająca się strona, więc pomyślałem, że przyda się innym w tej samej sytuacji.

 400
Author: kikito,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-11 19:04:00

Robi się to przez case w Ruby. Zobacz też Ten artykuł na Wikipedii.

Cytat:

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

Inny przykład:

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

Na stronie 123 (używam Kindle) w Ruby Lanugage (1st Edition, O ' Reilly), jest napisane, że słowo kluczowe then po klauzulach when można zastąpić znakiem nowej linii lub średnikiem (tak jak w składni if then else). (Ruby 1.8 pozwala również na dwukropek zamiast then... Ale składnia ta nie jest już dozwolona w Ruby 1.9.)

 190
Author: 太極者無極而生,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-08 02:40:33

Sprawa...kiedy

Aby dodać więcej przykładów do odpowiedź Chucka :

Z parametrem:

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

Bez parametru:

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

Proszę, bądźcie świadomiproblemu , który ostrzega kikito.

 88
Author: mmdemirbas,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:26:34

Wiele języków programowania, zwłaszcza tych wywodzących się z C, posiada wsparcie dla tak zwanegoSwitch Fallthrough . Szukałam najlepszego sposobu, aby zrobić to samo w Ruby i pomyślałam, że może się to przydać innym: {]}

W językach C-podobnych fallthrough zazwyczaj wygląda tak:

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;
}

W Rubim to samo można osiągnąć w następujący sposób:

case expression
when 'a', 'b', 'c'
  # Do something for a, b or c
when 'd', 'e'
  # Do something else for d or e
end

Nie jest to ściśle równoważne, ponieważ nie jest możliwe, aby 'a' wykonać blok kodu przed spadając do 'b' lub 'c', ale w większości uważam, że jest wystarczająco podobny, aby być użytecznym w ten sam sposób.

 65
Author: Robert Kajic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-06 01:59:39

W Rubim 2.0, Możesz również używać lambda w case instrukcjach, w następujący sposób:

is_even = ->(x) { x % 2 == 0 }

case number
when 0 then puts 'zero'
when is_even then puts 'even'
else puts 'odd'
end

Możesz również łatwo tworzyć własne komparatory za pomocą struktury z niestandardowym ===

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

(przykład zaczerpnięty z "czy procs może być używany z instrukcjami case w Ruby 2.0?".)

Lub, z pełną klasą:

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

(przykład zaczerpnięty z " Jak działa Instrukcja Case Ruby i co możesz z nią zrobić".)

 64
Author: James Lim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:55:11

Możesz używać wyrażeń regularnych, takich jak znajdowanie typu ciągu znaków:

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 użyje do tego operand równości === (dzięki @ JimDeville). Dodatkowe informacje są dostępne na stronie "operatory Ruby ". Można to również zrobić za pomocą przykładu @mmdemirbas (bez parametru), tylko takie podejście jest czystsze dla tego typu przypadków.

 48
Author: Haris Krajina,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-17 03:47:49

Jeśli chcesz wiedzieć, jak użyć warunku OR w przypadku przełącznika Ruby:

Tak więc, w case twierdzenie, , jest odpowiednikiem || w if twierdzenie.

case car
   when 'Maruti', 'Hyundai'
      # Code here
end

Wiele innych rzeczy, które możesz zrobić za pomocą instrukcji case Ruby

 30
Author: Manish Shrivastava,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-08 02:46:05

Nazywa się case i działa tak, jak można się spodziewać, plus dużo więcej zabawnych rzeczy dzięki uprzejmości ===, która wdraża testy.

case 5
  when 5
    puts 'yes'
  else
    puts 'else'
end

Teraz dla Zabawy:

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

I okazuje się, że możesz również zastąpić dowolny łańcuch if / else (to znaczy, nawet jeśli testy nie zawierają wspólnej zmiennej) case, pomijając początkowy parametr case i pisząc wyrażenia, w których pierwsze dopasowanie jest tym, czego chcesz.

case
  when x.nil?
    ...
  when (x.match /'^fn'/)
    ...
  when (x.include? 'substring')
    ...
  when x.gsub('o', 'z') == 'fnzrq'
    ...
  when Time.now.tuesday?
    ...
end
 25
Author: DigitalRoss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-30 22:48:00

W zależności od przypadku, możesz użyć hash metod.

Jeśli istnieje długa lista kiedy i każdy z nich ma konkretną wartość do porównania (nie interwał), bardziej efektywne będzie zadeklarowanie hasha metod, a następnie wywołanie odpowiedniej metody z tego hasha w ten sposób.

# 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])
 20
Author: Alexander,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-08 02:47:41

Ponieważ switch case zawsze Zwraca pojedynczy obiekt, możemy bezpośrednio wydrukować jego wynik:

puts case a
     when 0
        "It's zero"
     when 1
        "It's one"
     end
 19
Author: Sonu Oommen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-08 02:42:17

Wielowartościowe when i bez wartości case:

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

I Wyrażenie regularne rozwiązanie tutaj:

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
 19
Author: 123,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-08 02:45:03

Ruby używa case do pisania instrukcji switch.

Zgodnie z Ruby Docs :

Deklaracje przypadków składają się z warunku opcjonalnego, który jest w pozycja argumentu case i zero lub więcej when klauzul. Pierwsza when klauzula dopasowująca warunek (lub oceniająca do Boolean truth, jeśli warunek jest null)" wins", a jego strofa kodu jest wykonywany. Wartością instrukcji case jest wartość successful when klauzula, lub nil jeśli nie ma takiej klauzuli.

Deklaracja przypadku może zakończyć się klauzulą else. Każdy when a instrukcja może mieć wiele wartości kandydujących, oddzielonych przecinkami.

Przykład:

case x
when 1,2,3
  puts "1, 2, or 3"
when 10
  puts "10"
else
  puts "Some other number"
end

Wersja skrócona:

case x
when 1,2,3 then puts "1, 2, or 3"
when 10 then puts "10"
else puts "Some other number"
end

I jak ten blog by Honeybadger opisuje przypadek Ruby;

Może być używany z zakresami :

case 5
when (1..10)
  puts "case statements match inclusion in a range"
end

## => "case statements match inclusion in a range"

Może być używany z Regex :

case "FOOBAR"
when /BAR$/
  puts "they can match regular expressions!"
end

## => "they can match regular expressions!"

Może być używany z Procs i Lambda:

case 40
when -> (n) { n.to_s == "40" }
  puts "lambdas!"
end

## => "lambdas"

Może być również używany z własnymi klasami meczowymi:

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
 17
Author: Lahiru,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-22 09:27:32

W Rubim możesz pisać wyrażenia case na dwa różne sposoby.

  1. podobne do szeregu twierdzeń" if "
  2. określ cel obok przypadku i każda klauzula" kiedy " jest porównywana z celem.

Pierwsza droga

age = 20
case 
when age >= 21
puts "display something"
when 1 == 0
puts "omg"
else
puts "default condition"
end

Druga droga

 case params[:unknown]
 when /Something/ then 'Nothing'
 when /Something else/ then 'I dont know'
 end
 11
Author: ysk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-16 17:45:44

Wiele świetnych odpowiedzi, ale pomyślałem, że dodam jeden fakt.. Jeśli próbujesz porównać obiekty (klasy), upewnij się, że masz metodę statku kosmicznego (nie żart) lub zrozumieć, w jaki sposób są one porównywane

Oto dobra dyskusja na ten temat http://www.skorks.com/2009/09/ruby-equality-and-object-comparison/

 8
Author: jmansurf,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-08-06 20:18:37

Możesz to zrobić w bardziej naturalny sposób,]}

case expression
when condtion1
   function
when condition2
   function
else
   function
end
 8
Author: Navin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-26 09:15:12
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
 5
Author: Prabhakar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-12 06:33:17

Jak stwierdzono w wielu z powyższych odpowiedzi, operator === jest używany pod maską w poleceniach case / when.

Oto kilka dodatkowych informacji o tym operatorze.

Operator równości przypadków: = = =

Wiele wbudowanych klas Rubiego, takich jak String, Range i Regexp, dostarcza własnych implementacji operatora===, znanego również jako case-equality, triple equals lub threequals. Ponieważ jest zaimplementowany inaczej w każdej klasie, będzie zachowywał się inaczej w zależności na temat rodzaju obiektu, na który został wywołany. Zazwyczaj zwraca true, jeśli obiekt po prawej stronie "należy do "lub" jest członkiem " obiektu po lewej stronie. Na przykład, może być użyty do sprawdzenia, czy obiekt jest instancją klasy (lub jednej z jej podklas).

String === "zen"  # Output: => true
Range === (1..2)   # Output: => true
Array === [1,2,3]   # Output: => true
Integer === 2   # Output: => true

Ten sam wynik można osiągnąć za pomocą innych metod, które prawdopodobnie najlepiej nadają się do tego zadania, takich jak is_a? a instance_of?.

Implementacja zakresu = = =

Gdy operator = = = jest wywoływany na przedziale obiekt, zwraca true, jeśli wartość po prawej mieści się w zakresie po lewej stronie.

(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

Pamiętaj, że operator = = = wywołuje metodę = = = obiektu lewej ręki. So (1..4) = = = 3 jest równoważne (1..4).=== 3. Innymi słowy, Klasa operandu lewej strony określi, która implementacja metody === zostanie wywołana, więc pozycje operandu nie są wymienne.

Implementacja Regexp = = =

Zwraca true, jeśli łańcuch po prawej stronie pasuje do wyrażenia regularnego po lewej stronie. / zen / = = = "praktyka zazen dzisiaj" # wyjście: => true # jest podobny do "praktyka zazen dzisiaj" = ~/zen /

Jedyną istotną różnicą między dwoma powyższymi przykładami jest to, że gdy istnieje dopasowanie, = = = zwraca true i = ~ zwraca liczbę całkowitą, która jest prawdziwą wartością w Rubim. Wrócimy do tego wkrótce.

 4
Author: BrunoFacca,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-06 16:07:17
$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

Reference = > https://www.tutorialspoint.com/ruby/ruby_if_else.htm

 2
Author: Navneet,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-11-13 09:28:06

Zacząłem używać:

a = "secondcase"

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

puts var_name
>> "bar"

Pomaga skompaktować kod w niektórych przypadkach.

 1
Author: deepfritz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-08 02:46:39

Brak wsparcia dla wyrażeń regularnych w Twoim środowisku? E. g. Shopify Edytor skryptów (kwiecień, 2018):

[Error]: stała nieznitializowana RegExp

Obejście po kombinacji metod już wcześniej omówionych w tutaj i tutaj :

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

Użyłem ors w instrukcji metody klasy, ponieważ || ma wyższy priorytet niż .include?. Jeśli jesteś ruby-nazi, proszę. wyobraź sobie, że zamiast tego użyłem tego (item.include? 'A') || .... repl.it test.

 0
Author: CPHPython,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-18 11:29:29