Come scrivo una switch
dichiarazione in Ruby?
Come scrivo una switch
dichiarazione in Ruby?
Risposte:
Ruby usa invece l' case
espressione .
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 confronta l'oggetto nella when
clausola con l'oggetto nella case
clausola usando l' ===
operatore. Ad esempio 1..5 === x
, e non x === 1..5
.
Questo consente sofisticati when
clausole come visto sopra. Intervalli, classi e ogni genere di cose possono essere testati piuttosto che solo uguaglianza.
A differenza delle switch
affermazioni in molte altre lingue, Ruby case
non ha errori , quindi non è necessario terminare ognuna when
con un break
. Puoi anche specificare più corrispondenze in una singola when
clausola come when "foo", "bar"
.
when
e return
sulla stessa riga:when "foo" then "bar"
then
. Vedi anche le altre risposte.
case...when
si comporta un po 'inaspettatamente quando si gestiscono le classi. Ciò è dovuto al fatto che utilizza l' ===
operatore.
Quell'operatore funziona come previsto con i valori letterali, ma non con le classi:
1 === 1 # => true
Fixnum === Fixnum # => false
Ciò significa che se si desidera eseguire una case ... when
classe over di un oggetto, questo non funzionerà:
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
Stampa "Non è una stringa o un numero".
Fortunatamente, questo è facilmente risolvibile. L' ===
operatore è stato definito in modo che ritorni true
se lo usi con una classe e fornisci un'istanza di quella classe come secondo operando:
Fixnum === 1 # => true
In breve, il codice sopra può essere risolto rimuovendo .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
Oggi ho riscontrato questo problema mentre cercavo una risposta, e questa è stata la prima pagina che appare, quindi ho pensato che sarebbe stato utile per gli altri nella mia stessa situazione.
.class
parte in è interessante da notare, grazie. Certo, questo è un comportamento del tutto appropriato (anche se ho potuto vedere come potrebbe essere un errore comune pensare che verrebbe stampato It is a string
) ... stai testando la classe di qualche oggetto arbitrario, non l'oggetto stesso. Così, per esempio: case 'hello'.class when String then "String!" when Class then "Class!" else "Something else" end
i risultati a: "Class!"
Questo funziona lo stesso per 1.class
, {}.class
ecc Dropping .class
, si ottiene "String!"
o "Something else"
per questi diversi valori.
Viene fatto usando case
in Ruby. Vedi anche " Cambia istruzione " su Wikipedia.
citato:
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
Un altro esempio:
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
A pagina 123 di The Ruby Programming Language (1st Edition, O'Reilly) sul mio Kindle, si dice che la then
parola chiave che segue le when
clausole può essere sostituita con una nuova riga o punto e virgola (proprio come nella if then else
sintassi). (Ruby 1.8 consente anche i due punti al posto di then
, ma questa sintassi non è più consentita in Ruby 1.9.)
when (-1.0/0.0)..-1 then "Epic fail"
type = #{score}
ogni riga, posso semplicemente copiare quello che hai fatto. Molto più elegante, mi piacciono molto meglio anche i one-liner (se possibile)
Per aggiungere altri esempi alla risposta di Chuck :
Con parametro:
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
Senza parametro:
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
Si prega di essere consapevoli di " Come scrivere un'istruzione switch in Ruby " di cui kikito avverte.
or
Molti linguaggi di programmazione, in particolare quelli derivati da C, supportano il cosiddetto Switch Fallthrough . Stavo cercando il modo migliore per fare lo stesso in Ruby e ho pensato che potesse essere utile ad altri:
Nei linguaggi simili a C, generalmente il fallthrough appare così:
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;
}
In Ruby, lo stesso può essere ottenuto nel modo seguente:
case expression
when 'a', 'b', 'c'
# Do something for a, b or c
when 'd', 'e'
# Do something else for d or e
end
Questo non è strettamente equivalente, perché non è possibile consentire l' 'a'
esecuzione di un blocco di codice prima di passare a 'b'
o 'c'
, ma per la maggior parte lo trovo abbastanza simile da essere utile allo stesso modo.
In Ruby 2.0, puoi anche usare lambdas nelle case
istruzioni, come segue:
is_even = ->(x) { x % 2 == 0 }
case number
when 0 then puts 'zero'
when is_even then puts 'even'
else puts 'odd'
end
Puoi anche creare facilmente i tuoi comparatori usando un Struct con un'abitudine ===
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
(Esempio tratto da "I proc possono essere usati con le istruzioni case in Ruby 2.0? ".)
Oppure, con una classe completa:
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
(Esempio tratto da " Come funziona un'istruzione di un caso Ruby e cosa si può fare con esso ".)
Puoi usare espressioni regolari, come trovare un tipo di stringa:
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
Per questo Ruby case
utilizzerà l'operando di uguaglianza ===
(grazie a @JimDeville). Ulteriori informazioni sono disponibili su " Operatori Ruby ". Questo può essere fatto anche usando l'esempio @mmdemirbas (senza parametro), solo questo approccio è più pulito per questi tipi di casi.
Se sei ansioso di sapere come utilizzare una condizione OR in una custodia switch Ruby:
Quindi, in una case
dichiarazione, a ,
è l'equivalente di ||
in una if
dichiarazione.
case car
when 'Maruti', 'Hyundai'
# Code here
end
Vedi " Come funziona una dichiarazione del caso Ruby e cosa puoi farci ".
Si chiama case
e funziona come ci si aspetterebbe, oltre a molte altre cose divertenti per gentile concessione di ===
quali implementano i test.
case 5
when 5
puts 'yes'
else
puts 'else'
end
Ora per divertirti:
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
E si scopre che puoi anche sostituire una catena if / else arbitraria (cioè, anche se i test non coinvolgono una variabile comune) con case
tralasciando il case
parametro iniziale e scrivendo semplicemente espressioni in cui la prima corrispondenza è quella che desideri.
case
when x.nil?
...
when (x.match /'^fn'/)
...
when (x.include? 'substring')
...
when x.gsub('o', 'z') == 'fnzrq'
...
when Time.now.tuesday?
...
end
Ruby utilizza le case
istruzioni switch per la scrittura.
Secondo la case
documentazione:
Le dichiarazioni di casi sono costituite da una condizione facoltativa, che è nella posizione di un argomento
case
e da zero o piùwhen
clausole. La primawhen
clausola che corrisponde alla condizione (o per valutare la verità booleana, se la condizione è nulla) "vince" e la sua stanza del codice viene eseguita. Il valore dell'istruzione case è il valore dellawhen
clausola corretta , oppurenil
se non esiste tale clausola.Un'istruzione case può terminare con una
else
clausola. Ciascunawhen
istruzione può avere più valori candidati, separati da virgole.
Esempio:
case x
when 1,2,3
puts "1, 2, or 3"
when 10
puts "10"
else
puts "Some other number"
end
Versione più corta:
case x
when 1,2,3 then puts "1, 2, or 3"
when 10 then puts "10"
else puts "Some other number"
end
E come " Dichiarazione del caso di Ruby - tecniche avanzate " descrive Ruby case
;
Può essere utilizzato con gli intervalli :
case 5
when (1..10)
puts "case statements match inclusion in a range"
end
## => "case statements match inclusion in a range"
Può essere utilizzato con Regex :
case "FOOBAR"
when /BAR$/
puts "they can match regular expressions!"
end
## => "they can match regular expressions!"
Può essere utilizzato con Procs e Lambdas :
case 40
when -> (n) { n.to_s == "40" }
puts "lambdas!"
end
## => "lambdas"
Inoltre, può essere utilizzato con le tue classi di match:
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
A seconda del caso, potresti preferire utilizzare un hash di metodi.
Se esiste un lungo elenco di se when
ciascuno di essi ha un valore concreto da confrontare (non un intervallo), sarà più efficace dichiarare un hash di metodi e quindi chiamare il metodo rilevante dall'hash in quel modo.
# 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])
Poiché switch case
restituisce sempre un singolo oggetto, possiamo stampare direttamente il suo risultato:
puts case a
when 0
"It's zero"
when 1
"It's one"
end
Valore multiplo quando e nessun valore:
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
E una soluzione di espressione regolare qui:
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
(dove ,
significa newline)
Puoi scrivere case
espressioni in due modi diversi in Ruby:
if
affermazionicase
e ogni when
clausola viene confrontata con il target.age = 20
case
when age >= 21
puts "display something"
when 1 == 0
puts "omg"
else
puts "default condition"
end
o:
case params[:unknown]
when /Something/ then 'Nothing'
when /Something else/ then 'I dont know'
end
Molte risposte fantastiche, ma ho pensato di aggiungere un factoide. Se stai tentando di confrontare oggetti (Classi) assicurati di avere un metodo di nave spaziale (non uno scherzo) o di capire come vengono confrontati
" Ruby Equality And Object Comparison " è una buona discussione sull'argomento.
<=>
, che viene usato per restituire -1, 0, 1 o zero a seconda che il confronto ritorni rispettivamente minore di, uguale, maggiore di o non comparabile. La documentazione del modulo comparabile di Ruby lo spiega.
Come indicato in molte delle risposte di cui sopra, l' ===
operatore viene utilizzato sotto le istruzioni on case
/ hood when
.
Ecco ulteriori informazioni su quell'operatore:
===
Molte delle classi integrate di Ruby, come String, Range e Regexp, forniscono le proprie implementazioni ===
dell'operatore, note anche come "case-uguaglianza", "triple uguali" o "trequals". Poiché è implementato in modo diverso in ogni classe, si comporterà in modo diverso a seconda del tipo di oggetto su cui è stato chiamato. In genere, restituisce true se l'oggetto a destra "appartiene a" o "è un membro di" l'oggetto a sinistra. Ad esempio, può essere utilizzato per verificare se un oggetto è un'istanza di una classe (o una delle sue sottoclassi).
String === "zen" # Output: => true
Range === (1..2) # Output: => true
Array === [1,2,3] # Output: => true
Integer === 2 # Output: => true
Lo stesso risultato può essere ottenuto con altri metodi che sono probabilmente più adatti per il lavoro, come is_a?
einstance_of?
.
===
Quando l' ===
operatore viene chiamato su un oggetto intervallo, restituisce vero se il valore a destra rientra nell'intervallo a sinistra.
(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
Ricordare che l' ===
operatore invoca il ===
metodo dell'oggetto per la mano sinistra. Quindi (1..4) === 3
è equivalente a (1..4).=== 3
. In altre parole, la classe dell'operando di sinistra definirà quale implementazione del ===
metodo verrà chiamata, quindi le posizioni dell'operando non sono intercambiabili.
===
Restituisce vero se la stringa a destra corrisponde all'espressione regolare a sinistra.
/zen/ === "practice zazen today" # Output: => true
# is similar to
"practice zazen today"=~ /zen/
L'unica differenza rilevante tra i due esempi sopra è che, quando c'è una corrispondenza, ===
restituisce true e =~
restituisce un numero intero, che è un valore di verità in Ruby. Torneremo presto su questo.
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
Vedi " Ruby - if ... else, case, salvo " per maggiori informazioni.
Ho iniziato a usare:
a = "secondcase"
var_name = case a
when "firstcase" then "foo"
when "secondcase" then "bar"
end
puts var_name
>> "bar"
Aiuta in alcuni casi a compattare il codice.
Hash
, piuttosto che case
un'istruzione.
Nessun supporto per le espressioni regolari nel tuo ambiente? Ad esempio, Shopify Script Editor (aprile 2018):
[Errore]: RegExp costante non inizializzata
Una soluzione alternativa che segue una combinazione di metodi già precedentemente trattati qui e qui :
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
Ho usato or
s nell'istruzione del metodo di classe poiché ||
ha una precedenza più alta di
.include?
. Se sei un rubino-nazista , immagina di averlo usato (item.include? 'A') || ...
invece. test di repl.it.
È fondamentale enfatizzare la virgola ( ,
) in una when
clausola. Esso agisce come un ||
di if
dichiarazione, che è, lo fa un OR di confronto e non un E il confronto tra le espressioni delimitati della when
clausola. Vedi la seguente dichiarazione del caso:
x = 3
case x
when 3, x < 2 then 'apple'
when 3, x > 2 then 'orange'
end
=> "apple"
x
non è inferiore a 2, ma il valore restituito è "apple"
. Perché? Perché x
era 3 e da allora ',`` acts as an
|| , it did not bother to evaluate the expression
x <2 '.
Potresti pensare che per eseguire un AND , puoi fare qualcosa di simile qui sotto, ma non funziona:
case x
when (3 && x < 2) then 'apple'
when (3 && x > 2) then 'orange'
end
=> nil
Non funziona perché (3 && x > 2)
restituisce true e Ruby prende il valore True e lo confronta x
con ===
, il che non è vero, poiché x
è 3.
Per fare un &&
confronto, dovrai trattare case
come un blocco if
/ else
:
case
when x == 3 && x < 2 then 'apple'
when x == 3 && x > 2 then 'orange'
end
Nel libro Ruby Programming Language, Matz afferma che quest'ultima forma è la forma semplice (e usata raramente), che non è altro che una sintassi alternativa per if
/ elsif
/ else
. Tuttavia, sia che venga usato di rado o meno, non vedo nessun altro modo per allegare &&
espressioni multiple per una determinata when
clausola.
if...elsif
? Sembra che tu stia provando a mescolare un'istruzione case e una condizione. Perché? Basta inserire il condizionale all'interno del blocco when, ad es. when 3; ( x < 2 ) ? 'apple' : 'orange'
Possiamo scrivere un'istruzione switch per più condizioni.
Per esempio,
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
) Sono case-sensitive e non possono essere maiuscolo come questo.
NoMethodError (undefined method
CASE 'per main: Object) `. Come diceva @ sondra.kinsey, non è possibile utilizzare le maiuscole. Ruby penserà che sia una COSTANTE.
L' case
operatore dell'istruzione è simileswitch
nelle altre lingue.
Questa è la sintassi di switch...case
in C:
switch (expression)
{
case constant1:
// statements
break;
case constant2:
// statements
break;
.
.
.
default:
// default statements
}
Questa è la sintassi di case...when
in 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
Per esempio:
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
Per ulteriori informazioni consultare la case
documentazione.