Jak napisać switch
oświadczenie w Ruby?
Jak napisać switch
oświadczenie w Ruby?
Odpowiedzi:
Zamiast tego Ruby używa case
wyrażenia .
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 when
klauzuli z obiektem w case
klauzuli za pomocą ===
operatora. Na przykład 1..5 === x
i nie x === 1..5
.
Pozwala to na stosowanie wyrafinowanych when
klauzul, jak pokazano powyżej. Zakresy, klasy i wszelkiego rodzaju rzeczy mogą być testowane pod kątem nie tylko równości.
W przeciwieństwie do switch
stwierdzeń w wielu innych językach, Ruby's case
nie ma przewrotności , więc nie ma potrzeby kończenia każdego when
na break
. Możesz także określić wiele dopasowań w jednej when
klauzuli, takiej jak when "foo", "bar"
.
when
i return
w tym samym wierszu:when "foo" then "bar"
switch
stwierdzeń w wielu innych językach, Ruby case
NIE ma przewrotności , więc nie ma potrzeby kończenia każdego when
znakiem break
.
then
. Zobacz także inne odpowiedzi.
case...when
zachowuje się nieco nieoczekiwanie podczas obsługi klas. Wynika to z faktu, że korzysta on z ===
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
ponad 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 or number')
end
Wypisuje „To nie jest ciąg ani liczba”.
Na szczęście można to łatwo rozwiązać. ===
Operator został zdefiniowany tak, że wraca true
, jeśli używasz go z klasy i dostarczamy instancji tej klasy jako drugiego argumentu:
Fixnum === 1 # => true
Krótko mówiąc, 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 or number')
end
Znalazłem ten problem dzisiaj, szukając odpowiedzi, i to była pierwsza strona, więc pomyślałem, że przyda się innym w tej samej sytuacji.
.class
udział w Interesujący jest fakt, dzięki. Oczywiście, jest to całkowicie właściwe zachowanie (chociaż mogłem zobaczyć, jak często może się zdarzyć, że to się wydrukuje It is a string
) ... testujesz klasę dowolnego obiektu, a nie samego obiektu. Tak więc, na przykład: case 'hello'.class when String then "String!" when Class then "Class!" else "Something else" end
wyniki w: "Class!"
To działa tak samo na 1.class
, {}.class
itp spada .class
, mamy "String!"
lub "Something else"
dla tych różnych wartościach.
Odbywa się to za pomocą case
Ruby. Zobacz także „ Oświadczenie o zmianie” na Wikipedii.
Zacytowany:
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 The Ruby Programming Language (1st Edition, O'Reilly) na moim Kindle, napisano, że then
słowo kluczowe po when
klauzulach można zastąpić znakiem nowej linii lub średnikiem (tak jak w if then else
składni). (Ruby 1.8 zezwala również na dwukropek zamiast then
, ale ta składnia nie jest już dozwolona w Ruby 1.9.)
when (-1.0/0.0)..-1 then "Epic fail"
type = #{score}
każdą linię, mogę po prostu skopiować to, co zrobiłeś. O wiele bardziej elegancki Lubię też
Aby dodać więcej przykładów do odpowiedzi 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
Należy pamiętać o „ Jak napisać instrukcję zmiany w Ruby ”, o której ostrzega kikito.
or
Wiele języków programowania, zwłaszcza tych pochodzących z C, obsługuje tak zwany Switch Fallthrough . Szukałem najlepszego sposobu, aby zrobić to samo w Ruby i pomyślałem, że może być przydatny dla innych:
W językach podobnych do C przegląd zwykle wygląda następująco:
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 Ruby 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 'a'
wykonanie bloku kodu przed wpadnięciem do 'b'
lub 'c'
, ale w przeważającej części uważam, że jest wystarczająco podobny, aby był użyteczny w ten sam sposób.
W Ruby 2.0 możesz również używać lambd 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 także łatwo tworzyć własne komparatory za pomocą Struct 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 wzięty z „ Czy można używać procs 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 Ruby Case i co możesz z tym zrobić ”).
Możesz użyć wyrażeń regularnych, takich jak znalezienie typu ciągu:
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 case
użyje ===
do tego operandu równości (dzięki @JimDeville). Dodatkowe informacje są dostępne w „ Ruby Operators ”. Można to również zrobić na przykładzie @mmdemirbas (bez parametru), tylko takie podejście jest czystsze dla tego typu przypadków.
Jeśli chcesz wiedzieć, jak używać warunku OR w obudowie przełącznika Ruby:
Tak więc, w case
zestawieniu, na ,
to odpowiednik ||
w if
oświadczeniu.
case car
when 'Maruti', 'Hyundai'
# Code here
end
Zobacz „ Jak działa instrukcja Ruby Case i co możesz z tym zrobić ”.
Nazywa się case
i działa tak, jak można się spodziewać, a także o wiele więcej zabawy dzięki uprzejmości, ===
która implementuje testy.
case 5
when 5
puts 'yes'
else
puts 'else'
end
Teraz trochę 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
Okazuje się, że możesz również zastąpić dowolny łańcuch if / else (to znaczy nawet jeśli testy nie obejmują wspólnej zmiennej) case
, pomijając case
parametr początkowy i zapisują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
Ruby używa case
do pisania instrukcji switch.
Zgodnie z case
dokumentacją:
Instrukcje case składają się z warunku opcjonalnego, który jest w pozycji argumentu
case
, i zero lub więcejwhen
klauzul. Pierwszawhen
klauzula, która pasuje do warunku (lub do oceny logicznej prawdy, jeśli warunek jest pusty) „wygrywa”, a sekcja kodu jest wykonywana. Wartość instrukcji case jest wartością pomyślnejwhen
klauzuli lubnil
jeśli takiej klauzuli nie ma.Instrukcja case może kończyć się
else
klauzulą. Każdawhen
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
Krótsza wersja:
case x
when 1,2,3 then puts "1, 2, or 3"
when 10 then puts "10"
else puts "Some other number"
end
A jako „ Deklaracja przypadku Ruby - zaawansowane techniki ” opisuje Ruby case
;
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ć stosowany z Regex :
case "FOOBAR"
when /BAR$/
puts "they can match regular expressions!"
end
## => "they can match regular expressions!"
Może być stosowany z Procs i Lambdas :
case 40
when -> (n) { n.to_s == "40" }
puts "lambdas!"
end
## => "lambdas"
Ponadto można go używać z własnymi klasami meczów:
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
W zależności od przypadku możesz użyć skrótu metod.
Jeśli istnieje długa lista when
s, a każda z nich ma konkretną wartość do porównania (nie interwał), skuteczniej będzie zadeklarować skrót metod, a następnie wywołać odpowiednią metodę z takiego skrótu.
# 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])
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
Przypadek wielowartościowy, gdy i bez wartości:
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 tutaj rozwiązanie wyrażeń regularnych :
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
(gdzie ,
oznacza nowy wiersz)
W case
Ruby możesz pisać wyrażenia na dwa różne sposoby:
if
stwierdzeńcase
a każda when
klauzula jest porównywana z celem.age = 20
case
when age >= 21
puts "display something"
when 1 == 0
puts "omg"
else
puts "default condition"
end
lub:
case params[:unknown]
when /Something/ then 'Nothing'
when /Something else/ then 'I dont know'
end
Wiele świetnych odpowiedzi, ale pomyślałem, że dodam jeden faktoid. Jeśli próbujesz porównać obiekty (klasy), upewnij się, że masz metodę statku kosmicznego (nie żart) lub zrozum, jak są porównywane
„ Ruby Equality And Object Porównanie ” to dobra dyskusja na ten temat.
<=>
jest używana do zwracania wartości -1, 0, 1 lub zero w zależności od tego, czy porównanie zwraca odpowiednio mniej niż, równość, więcej niż lub nieporównywalnie. Wyjaśnia to dokumentacja modułu Ruby Porównywalna .
Jak stwierdzono w wielu powyższych odpowiedziach, ===
operator jest używany pod maską case
/ when
instrukcji.
Oto dodatkowe informacje o tym operatorze:
===
Wiele wbudowanych klas Ruby, takich jak String, Range i Regexp, zapewnia własne implementacje ===
operatora, znanego również jako „równość wielkości liter”, „trzykrotnie równe” lub „trzykwale”. Ponieważ jest zaimplementowany inaczej w każdej klasie, będzie zachowywać się inaczej w zależności od typu obiektu, do którego został wywołany. Zasadniczo zwraca wartość true, jeśli obiekt po prawej „należy do” lub „jest członkiem” obiektu po lewej stronie. Na przykład można go użyć do przetestowania, czy obiekt jest instancją klasy (lub jednej z jego 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 pracy, takich jak is_a?
i instance_of?
.
===
Gdy ===
operator jest wywoływany na obiekcie zakresu, zwraca wartość true, jeśli wartość po prawej stronie 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 po lewej stronie. Więc (1..4) === 3
jest równoważna (1..4).=== 3
. Innymi słowy, klasa operandu po lewej stronie określi, która implementacja ===
metody zostanie wywołana, więc pozycje operandu nie są wymienne.
===
Zwraca true, jeśli ciąg po prawej stronie pasuje do wyrażenia regularnego po lewej.
/zen/ === "practice zazen today" # Output: => true
# is similar to
"practice zazen today"=~ /zen/
Jedyną istotną różnicą między dwoma powyższymi przykładami jest to, że gdy występuje dopasowanie, ===
zwraca true i =~
zwraca liczbę całkowitą, która jest prawdą w Rubim. Wrócimy do tego wkrótce.
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
Aby uzyskać więcej informacji, zobacz „ Ruby - jeśli ... w innym przypadku, chyba że ”.
Zacząłem używać:
a = "secondcase"
var_name = case a
when "firstcase" then "foo"
when "secondcase" then "bar"
end
puts var_name
>> "bar"
W niektórych przypadkach pomaga to w kompaktowaniu kodu.
Hash
pomocą case
instrukcji , a nie instrukcji.
Brak obsługi wyrażeń regularnych w twoim środowisku? Np. Shopify Script Editor (kwiecień, 2018):
[Błąd]: niezainicjowana stała RegExp
Obejście po kombinacji metod już wcześniej omawianych 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 or
s w instrukcji metody class, ponieważ ||
ma wyższy priorytet niż
.include?
. Jeśli jesteś rubinowym nazistą , wyobraź sobie, że użyłem tego (item.include? 'A') || ...
zamiast tego . test repl.it.
Bardzo ważne jest podkreślenie przecinka ( ,
) w when
zdaniu. Działa jako ||
o if
oświadczeniu, to znaczy, że robi LUB porównania, a nie I Porównanie ustalonych wyrażeń when
klauzuli. Zobacz następującą instrukcję przypadku:
x = 3
case x
when 3, x < 2 then 'apple'
when 3, x > 2 then 'orange'
end
=> "apple"
x
jest nie mniejsza niż 2, ale zwracana jest wartość "apple"
. Dlaczego? Ponieważ x
było 3, a od ',`` acts as an
|| , it did not bother to evaluate the expression
x <2 '.
Możesz pomyśleć, że aby wykonać operację AND , możesz zrobić coś takiego poniżej, ale to nie działa:
case x
when (3 && x < 2) then 'apple'
when (3 && x > 2) then 'orange'
end
=> nil
Nie działa, ponieważ (3 && x > 2)
zwraca wartość true, a Ruby przyjmuje wartość True i porównuje ją x
z ===
, co nie jest prawdą, ponieważ x
wynosi 3.
Aby dokonać &&
porównania, będziesz musiał traktować case
jak if
/ else
block:
case
when x == 3 && x < 2 then 'apple'
when x == 3 && x > 2 then 'orange'
end
W książce Ruby Programming Language Matz mówi, że ta ostatnia forma jest prostą (i rzadko używaną) formą, która jest niczym innym jak alternatywną składnią dla if
/ elsif
/ else
. Jednak niezależnie od tego, czy jest to rzadko używane, czy nie, nie widzę innego sposobu na dołączenie wielu &&
wyrażeń dla danej when
klauzuli.
if...elsif
? Wygląda na to, że próbujesz połączyć instrukcję przypadku i warunek. Dlaczego? Wystarczy umieścić warunek wewnątrz bloku when, np. when 3; ( x < 2 ) ? 'apple' : 'orange'
Możemy napisać instrukcję switch dla wielu warunków.
Na przykład,
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
) Są wrażliwe na wielkość liter i nie może być tak wielka.
NoMethodError (undefined method
CASE 'dla main: Object) `. Jak powiedział @ sondra.kinsey, nie można używać wielkich liter. Ruby pomyśli, że to STAŁA.
case
Operator stwierdzenie jest jak switch
w innych językach.
Oto składnia switch...case
w C:
switch (expression)
{
case constant1:
// statements
break;
case constant2:
// statements
break;
.
.
.
default:
// default statements
}
Oto składnia case...when
w 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
Na przykład:
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
Aby uzyskać więcej informacji, zobacz case
dokumentację.