¿Cómo escribir una sentencia switch en Ruby?
¿Cómo escribo una instrucción switch en Ruby?
21 answers
Ruby utiliza el case
expression 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 cláusula when
con el objeto en la cláusula case
usando el operador ===
. Por ejemplo, 1..5 === x
, y no x === 1..5
.
Esto permite cláusulas when
sofisticadas como se ha visto anteriormente. Rangos, clases y todo tipo de cosas se pueden probar en lugar de solo la igualdad.
A diferencia de switch
declaraciones en muchos otros idiomas, Ruby case
no tiene fall-through, por lo que no hay necesidad de terminar cada when
con un break
. También puede especificar varias coincidencias en una sola cláusula when
como when "foo", "bar"
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-04 09:03:49
case...when
se comporta un poco inesperadamente al manejar clases. Esto se debe al hecho de que utiliza el operador ===
.
Ese operador funciona como se espera con literales, pero no con clases:
1 === 1 # => true
Fixnum === Fixnum # => false
Esto significa que si desea hacer un case ... when
sobre la clase de 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')
end
Imprimirá "No es una cadena".
Afortunadamente, esto se resuelve fácilmente. El operador ===
ha sido definido para que devuelva true
si lo usa con una clase y suministrar una instancia de esa clase como el segundo operando:
Fixnum === 1 # => true
En resumen, el código anterior se puede arreglar eliminando el .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
Hoy encontré este problema 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.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-11 19:04:00
Se hace por case en Ruby. También ver este artículo 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 (estoy usando Kindle) de El Lanugage de Programación Ruby (1ª Edición, O'Reilly), dice que la palabra clave then
después de las cláusulas when
se puede reemplazar con una nueva línea o punto y coma (al igual que en la sintaxis if then else
). (Ruby 1.8 también permite dos puntos en lugar de then
... Pero esta sintaxis ya no está permitida en Ruby 1.9.)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-08 02:40:33
Caso...cuando
Para agregar más ejemplos a La respuesta de Chuck :
Con el 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
Por favor, tenga en cuenta el problema que kikito advierte.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:26:34
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 lenguajes similares a C, fallthrough normalmente 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, lo mismo se puede lograr 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 que 'a'
ejecute un bloque de código antes cayendo a través de 'b'
o 'c'
, pero en su mayor parte lo encuentro lo suficientemente similar como para ser útil de la misma manera.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-05-06 01:59:39
En Ruby 2.0, también puede usar lambdas en las sentencias case
, 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 una estructura con un ===
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 puede usar procs con sentencias case 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 Sentencia Ruby Case Y Qué Se Puede Hacer Con Ella".)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:55:11
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 case
utilizará 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 que este enfoque es más limpio para este tipo de casos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-17 03:47:49
Si está ansioso por saber cómo usar una condición OR en un caso de Ruby switch:
Así, en una sentencia case
, a ,
es el equivalente de ||
en una sentencia if
.
case car
when 'Maruti', 'Hyundai'
# Code here
end
Muchas otras cosas que puedes hacer con una sentencia Ruby case
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-08 02:46:05
Se llama case
y funciona como cabría esperar, además de muchas cosas más divertidas cortesía de ===
que implementa las pruebas.
case 5
when 5
puts 'yes'
else
puts 'else'
end
Ahora para un poco de diversión:
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) con case
omitiendo el parámetro inicial case
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-30 22:48:00
Dependiendo de su caso, podría preferir usar un hash de métodos.
Si hay una larga lista de cuándo y 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 desde el 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])
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-08 02:47:41
Dado que 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-08 02:42:17
Multi-valor cuando y caso 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 expresión regular solución 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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-08 02:45:03
Ruby usa case
para escribir sentencias switch.
Según los Documentos de Ruby :
Las sentencias Case consisten en una condición opcional, que posición de un argumento a
case
, y cero o máswhen
cláusulas. La primera cláusulawhen
para que coincida con la condición (o para evaluar a Verdad booleana, si la condición es nula) "gana", y su estrofa de código es ejecutado. El valor de la sentencia case es el valor de la la cláusulawhen
exitosa, onil
si no existe tal cláusula.Una sentencia case puede terminar con una cláusula
else
. Cadawhen
a la instrucció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 este blog de Honeybadger describe 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 utilizar con Regex :
case "FOOBAR"
when /BAR$/
puts "they can match regular expressions!"
end
## => "they can match regular expressions!"
Puede utilizarse con Procs y Lambdas :
case 40
when -> (n) { n.to_s == "40" }
puts "lambdas!"
end
## => "lambdas"
También, se puede utilizar con sus propias clases de partido:
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-22 09:27:32
Puede escribir expresiones de mayúsculas y minúsculas de dos maneras diferentes en ruby.
- Similar a una serie de declaraciones "if"
- Especifique un destino junto al caso y cada cláusula "when" se compara con el destino.
1er camino
age = 20
case
when age >= 21
puts "display something"
when 1 == 0
puts "omg"
else
puts "default condition"
end
2da manera
case params[:unknown]
when /Something/ then 'Nothing'
when /Something else/ then 'I dont know'
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-16 17:45:44
Un montón de grandes respuestas, pero pensé que podría añadir un factoid.. Si está intentando comparar objetos (Clases) asegúrese de tener un método de nave espacial (no es una broma) o entender cómo se están comparando
Aquí hay una buena discusión sobre el tema http://www.skorks.com/2009/09/ruby-equality-and-object-comparison /
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-08-06 20:18:37
Puedes hacer esto de una manera más natural,
case expression
when condtion1
function
when condition2
function
else
function
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-12 06:33:17
Como se indica en muchas de las respuestas anteriores, el operador === se usa bajo el capó en las sentencias case/when.
Aquí hay algunas informaciones adicionales sobre ese operador.
Operador de igualdad de casos: = = =
Muchas de las clases integradas de Ruby, como String, Range y Regexp, proporcionan sus propias implementaciones del operador===, también conocido como case-equality, triple equals o threequals. Debido a que se implementa de manera diferente en cada clase, se comportará de manera diferente dependiendo sobre el tipo de objeto al que fue llamado. Generalmente, devuelve true si el objeto de la derecha "pertenece a" o "es un miembro de" el 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
El mismo resultado se puede lograr con otros métodos que probablemente sean los más adecuados para el trabajo, como is_a? y instance_of?.
Implementación de rango de = = =
Cuando se llama al operador = = = en un rango objeto, devuelve true 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 izquierdo. So (1..4) = = = 3 es equivalente a (1..4).=== 3. En otras palabras, la clase del operando izquierdo definirá qué implementación del método === se llamará, por lo que las posiciones del operando no son intercambiables.
Regexp Implementación de = = =
Devuelve true si la cadena de la derecha coincide con la expresión regular de la izquierda. / zen / = = = "practice zazen today" # Output: = > true # es similar a "practice zazen today" = ~/zen /
La única diferencia relevante entre los dos ejemplos anteriores es que, cuando hay una coincidencia, === devuelve true y =~ devuelve un entero, que es un valor truth en Ruby. Volveremos a esto pronto.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
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
Referencia => https://www.tutorialspoint.com/ruby/ruby_if_else.htm
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-13 09:28:06
He empezado a usar:
a = "secondcase"
var_name = case a
when "firstcase" then "foo"
when "secondcase" then "bar"
end
puts var_name
>> "bar"
Ayuda a compactar el código en algunos casos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-08-08 02:46:39
No hay soporte para expresiones regulares en su entorno? E. g. Shopify Editor de scripts (abril, 2018):
[Error]: constante no inicializada RegExp
Una solución alternativa siguiendo una combinación de métodos ya cubiertos previamente en 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 instrucción class method ya que ||
tiene mayor precedencia que
.include?
. Si usted es un ruby-nazi, por favor imagina que usé esto (item.include? 'A') || ...
en su lugar. repl.it prueba.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-18 11:29:29