¿Cómo escribo una switch
declaración en Ruby?
¿Cómo escribo una switch
declaración en Ruby?
Respuestas:
Ruby usa la case
expresión en su lugar.
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 compara el objeto en la when
cláusula con el objeto en la case
cláusula usando el ===
operador. Por ejemplo, 1..5 === x
y no x === 1..5
.
Esto permite when
cláusulas sofisticadas como se ve arriba. Los rangos, las clases y todo tipo de cosas se pueden probar en lugar de solo la igualdad.
A diferencia de las switch
declaraciones en muchos otros idiomas, Ruby's case
no tiene fallos, por lo que no es necesario terminar cada uno when
con un break
. También puede especificar múltiples coincidencias en una sola when
cláusula como when "foo", "bar"
.
when
y return
en la misma línea:when "foo" then "bar"
switch
declaraciones en muchos otros idiomas, Ruby's case
NO tiene fallos, por lo que no hay necesidad de terminar cada uno when
con un break
.
then
. Por favor, vea también las otras respuestas.
case...when
se comporta un poco inesperadamente cuando maneja clases. Esto se debe al hecho de que utiliza el ===
operador.
Ese operador funciona como se esperaba con literales, pero no con clases:
1 === 1 # => true
Fixnum === Fixnum # => false
Esto significa que si desea hacer una case ... when
clase sobre un objeto, esto no funcionará:
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
Imprimirá "No es una cadena o número".
Afortunadamente, esto se resuelve fácilmente. El ===
operador se ha definido para que regrese true
si lo usa con una clase y proporciona una instancia de esa clase como el segundo operando:
Fixnum === 1 # => true
En resumen, el código anterior se puede solucionar eliminando .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
Encontré este problema hoy mientras buscaba una respuesta, y esta fue la primera página que apareció, así que pensé que sería útil para otros en mi misma situación.
.class
parte en Es interesante observar, gracias. Por supuesto, este es un comportamiento completamente apropiado (aunque podría ver cómo podría ser un error común pensar que se imprimiría It is a string
) ... está probando la clase de algún objeto arbitrario, no el objeto en sí. Así, por ejemplo: case 'hello'.class when String then "String!" when Class then "Class!" else "Something else" end
los resultados en: "Class!"
Esto funciona de la misma para 1.class
, {}.class
, etc caída .class
, obtenemos "String!"
o "Something else"
para estos diversos valores.
Se hace usando case
en Ruby. Consulte también " Cambiar declaración " en Wikipedia.
Citado:
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
Otro ejemplo:
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
Alrededor de la página 123 de The Ruby Programming Language (1st Edition, O'Reilly) en mi Kindle, dice que la then
palabra clave que sigue a las when
cláusulas se puede reemplazar con una nueva línea o punto y coma (como en la if then else
sintaxis). (Ruby 1.8 también permite dos puntos en lugar de then
, pero esta sintaxis ya no está permitida en Ruby 1.9).
when (-1.0/0.0)..-1 then "Epic fail"
type = #{score}
cada línea, simplemente puedo copiar lo que hiciste. Mucho más elegante, también me gustan mucho los one-liners (si es posible)
Para agregar más ejemplos a la respuesta de Chuck :
Con parámetro:
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
Sin parámetro:
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
Tenga en cuenta " Cómo escribir una declaración de cambio en Ruby " sobre el que advierte kikito.
or
Muchos lenguajes de programación, especialmente los derivados de C, tienen soporte para el llamado Switch Fallthrough . Estaba buscando la mejor manera de hacer lo mismo en Ruby y pensé que podría ser útil para otros:
En los lenguajes tipo C, la caída generalmente se ve así:
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;
}
En Ruby, se puede lograr lo mismo de la siguiente manera:
case expression
when 'a', 'b', 'c'
# Do something for a, b or c
when 'd', 'e'
# Do something else for d or e
end
Esto no es estrictamente equivalente, porque no es posible dejar 'a'
ejecutar un bloque de código antes de caer en 'b'
o 'c'
, pero en su mayor parte lo encuentro lo suficientemente similar como para ser útil de la misma manera.
En Ruby 2.0, también puede usar lambdas en case
declaraciones, de la siguiente manera:
is_even = ->(x) { x % 2 == 0 }
case number
when 0 then puts 'zero'
when is_even then puts 'even'
else puts 'odd'
end
También puede crear sus propios comparadores fácilmente usando un Struct con un personalizado ===
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
(Ejemplo tomado de " ¿Se pueden usar procs con declaraciones de caso en Ruby 2.0? ").
O, con una clase 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
(Ejemplo tomado de " Cómo funciona una declaración de caso Ruby y qué puede hacer con ella ").
Puede usar expresiones regulares, como encontrar un tipo de cadena:
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
usará el operando de igualdad ===
para esto (gracias @JimDeville). Hay información adicional disponible en " Operadores de Ruby ". Esto también se puede hacer usando el ejemplo @mmdemirbas (sin parámetro), solo este enfoque es más limpio para este tipo de casos.
Si está ansioso por saber cómo usar una condición OR en una caja de interruptor Ruby:
Entonces, en una case
declaración, a ,
es el equivalente de ||
en una if
declaración.
case car
when 'Maruti', 'Hyundai'
# Code here
end
Consulte " Cómo funciona una declaración de caso Ruby y qué puede hacer con ella ".
Se llama case
y funciona como era de esperar, además de muchas más cosas divertidas, cortesía de las ===
cuales implementan las pruebas.
case 5
when 5
puts 'yes'
else
puts 'else'
end
Ahora para divertirse:
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
Y resulta que también puede reemplazar una cadena arbitraria if / else (es decir, incluso si las pruebas no involucran una variable común) case
omitiendo el case
parámetro inicial y simplemente escribiendo expresiones donde la primera coincidencia es lo que desea.
case
when x.nil?
...
when (x.match /'^fn'/)
...
when (x.include? 'substring')
...
when x.gsub('o', 'z') == 'fnzrq'
...
when Time.now.tuesday?
...
end
Ruby usa el case
para escribir declaraciones de cambio.
Según la case
documentación:
Las declaraciones de caso consisten en una condición opcional, que está en la posición de un argumento a
case
, y cero o máswhen
cláusulas. La primerawhen
cláusula para hacer coincidir la condición (o para evaluar la verdad booleana, si la condición es nula) "gana", y se ejecuta su estrofa de código. El valor de la declaración del caso es el valor de lawhen
cláusula exitosa , onil
si no existe tal cláusula.Una declaración de caso puede terminar con una
else
cláusula. Cadawhen
una declaración puede tener múltiples valores candidatos, separados por comas.
Ejemplo:
case x
when 1,2,3
puts "1, 2, or 3"
when 10
puts "10"
else
puts "Some other number"
end
Versión más corta:
case x
when 1,2,3 then puts "1, 2, or 3"
when 10 then puts "10"
else puts "Some other number"
end
Y como " Declaración del caso de Ruby - técnicas avanzadas " describe a Ruby case
;
Se puede usar con rangos :
case 5
when (1..10)
puts "case statements match inclusion in a range"
end
## => "case statements match inclusion in a range"
Se puede usar con Regex :
case "FOOBAR"
when /BAR$/
puts "they can match regular expressions!"
end
## => "they can match regular expressions!"
Se puede usar con Procs y Lambdas :
case 40
when -> (n) { n.to_s == "40" }
puts "lambdas!"
end
## => "lambdas"
Además, puede usarse con sus propias clases de coincidencia:
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
Dependiendo de su caso, podría preferir utilizar un hash de métodos.
Si hay una larga lista de when
sy cada uno de ellos tiene un valor concreto para comparar (no un intervalo), será más efectivo declarar un hash de métodos y luego llamar al método relevante del hash de esa manera.
# 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])
Como switch case
siempre devuelve un único objeto, podemos imprimir directamente su resultado:
puts case a
when 0
"It's zero"
when 1
"It's one"
end
Caso de valor múltiple cuando y sin valor:
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
Y una solución de expresión regular aquí:
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
(donde ,
significa nueva línea)
Puedes escribir case
expresiones de dos maneras diferentes en Ruby:
if
declaracionescase
y cada when
cláusula se compara con el objetivo.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
Muchas respuestas geniales, pero pensé que agregaría un factoide. Si estás intentando comparar objetos (clases), asegúrate de tener un método de nave espacial (no una broma) o entender cómo se están comparando.
" Ruby Equality And Object Comparison " es una buena discusión sobre el tema.
<=>
, que se utiliza para devolver -1, 0, 1 o cero, dependiendo de si la comparación devuelve menor que, igual, mayor que o no comparable, respectivamente. La documentación del módulo comparable de Ruby lo explica.
Como se indica en muchas de las respuestas anteriores, el ===
operador se utiliza bajo el capó en case
/ when
declaraciones.
Aquí hay información adicional sobre ese operador:
===
Muchas de las clases integradas de Ruby, como String, Range y Regexp, proporcionan sus propias implementaciones del ===
operador, también conocido como "igualdad de casos", "triple igual" o "tres iguales". Debido a que se implementa de manera diferente en cada clase, se comportará de manera diferente según el tipo de objeto al que se llamó. En general, devuelve verdadero si el objeto de la derecha "pertenece" o "es miembro del" objeto de la izquierda. Por ejemplo, se puede usar para probar si un objeto es una instancia de una clase (o una de sus subclases).
String === "zen" # Output: => true
Range === (1..2) # Output: => true
Array === [1,2,3] # Output: => true
Integer === 2 # Output: => true
Se puede lograr el mismo resultado con otros métodos que probablemente sean los más adecuados para el trabajo, como is_a?
y instance_of?
.
===
Cuando ===
se llama al operador en un objeto de rango, devuelve verdadero si el valor de la derecha cae dentro del rango de la izquierda.
(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
Recuerde que el ===
operador invoca el ===
método del objeto de la izquierda. Entonces (1..4) === 3
es equivalente a (1..4).=== 3
. En otras palabras, la clase del operando de la izquierda definirá a qué implementación del ===
método se llamará, por lo que las posiciones de los operandos no son intercambiables.
===
Devuelve verdadero si la cadena de la derecha coincide con la expresión regular de la izquierda.
/zen/ === "practice zazen today" # Output: => true
# is similar to
"practice zazen today"=~ /zen/
La única diferencia relevante entre los dos ejemplos anteriores es que, cuando hay una coincidencia, ===
devuelve verdadero y =~
devuelve un entero, que es un valor verdadero en Ruby. Volveremos a esto pronto.
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
Para obtener más información, consulte " Ruby: si ... si no, caso, a menos que ".
Empecé a usar:
a = "secondcase"
var_name = case a
when "firstcase" then "foo"
when "secondcase" then "bar"
end
puts var_name
>> "bar"
Ayuda a compactar código en algunos casos.
Hash
, en lugar de una case
declaración.
¿No hay soporte para expresiones regulares en su entorno? Por ejemplo, Shopify Script Editor (abril de 2018):
[Error]: constante RegExp no inicializada
Una solución alternativa que sigue una combinación de métodos ya cubiertos anteriormente aquí y aquí :
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
Usé or
s en la declaración del método de clase ya que ||
tiene mayor prioridad que
.include?
. Si eres un rubí-nazi , imagina que usé esto (item.include? 'A') || ...
en su lugar. repl.it test.
Es crítico enfatizar la coma ( ,
) en una when
cláusula. Actúa como ||
de una if
declaración, es decir, se hace un OR de comparación y no un Y la comparación entre las expresiones delimitadas de la when
cláusula. Vea la siguiente declaración de caso:
x = 3
case x
when 3, x < 2 then 'apple'
when 3, x > 2 then 'orange'
end
=> "apple"
x
no es menor que 2, pero el valor de retorno es "apple"
. ¿Por qué? Porque x
era 3 y desde ',`` acts as an
|| , it did not bother to evaluate the expression
x <2 '.
Puede pensar que para realizar un AND , puede hacer algo como esto a continuación, pero no funciona:
case x
when (3 && x < 2) then 'apple'
when (3 && x > 2) then 'orange'
end
=> nil
No funciona porque se (3 && x > 2)
evalúa como verdadero, y Ruby toma el valor Verdadero y lo compara x
con ===
, lo cual no es cierto, ya quex
es 3.
Para hacer una &&
comparación, tendrá que tratar case
como un if
/ else
bloque:
case
when x == 3 && x < 2 then 'apple'
when x == 3 && x > 2 then 'orange'
end
En el libro Ruby Programming Language, Matz dice que esta última forma es la forma simple (y que se usa con poca frecuencia), que no es más que una sintaxis alternativa para if
/ elsif
/ else
. Sin embargo, si se usa con poca frecuencia o no, no veo ninguna otra forma de adjuntar múltiples &&
expresiones para una when
cláusula dada .
if...elsif
? Parece que estás tratando de mezclar una declaración de caso y una condición. ¿Por qué? Simplemente ponga el condicional dentro del bloque when, por ejemplo. when 3; ( x < 2 ) ? 'apple' : 'orange'
Podemos escribir una declaración de cambio para múltiples condiciones.
Por ejemplo,
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
) Entre mayúsculas y minúsculas y no pueden estar en mayúsculas como este.
NoMethodError (undefined method
CASO 'para main: Object) `. Como dijo @ sondra.kinsey, no puedes usar mayúsculas. Ruby pensará que es CONSTANTE.
El case
operador de declaración es comoswitch
en los otros idiomas.
Esta es la sintaxis de switch...case
en C:
switch (expression)
{
case constant1:
// statements
break;
case constant2:
// statements
break;
.
.
.
default:
// default statements
}
Esta es la sintaxis de case...when
en 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
Por ejemplo:
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
Para más información ver el case
documentación.