rails - Cómo escribir una instrucción switch en Ruby
rails case when default (21)
¿Cómo escribo una declaración de cambio en Ruby?
caso ... cuando
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
Por favor, tenga en cuenta el problema que advierte kikito.
¿No hay soporte para expresiones regulares en su entorno? Ej. Shopify Script Editor (abril, 2018):
[Error]: RegExp constante sin inicializar
Una solución que sigue una combinación de métodos ya cubiertos anteriormente here y here :
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 desde ||
tiene mayor precedencia que .include?
. Si eres un ruby-nazi , imagina que usé esto (item.include? ''A'') || ...
(item.include? ''A'') || ...
lugar prueba de repl.it
Como se indica en muchas de las respuestas anteriores, el operador === se usa bajo el capó en las declaraciones de caso / cuándo.
Aquí hay algunos datos adicionales sobre ese operador.
Operador de igualdad de casos: ===
Muchas de las clases incorporadas de Ruby, como String, Range y Regexp, proporcionan sus propias implementaciones del operador ===, también conocido como igualdad de casos, triple igual o triple calidad. 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 a" o "es 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 instancia_de?
Rango de Implementación de ===
Cuando se llama al operador === en un objeto de rango, devuelve verdadero si el valor de la derecha se encuentra 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á qué implementación del método === será Llamado, por lo que las posiciones del operando no son intercambiables.
Implementación Regexp de ===
Devuelve verdadero si la cadena de la derecha coincide con la expresión regular de la izquierda. / zen / === "practicar zazen hoy" # Salida: => verdadero # es similar a "practicar zazen hoy" = ~ / 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 verdadero en Ruby. Volveremos a esto pronto.
Dado que switch case
siempre devuelve un solo objeto, podemos imprimir directamente su resultado:
puts case a
when 0
"It''s zero"
when 1
"It''s one"
end
Dependiendo de su caso, podría preferir utilizar 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 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])
En Ruby 2.0, también puede usar lambdas en declaraciones de 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 utilizando 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 casos en Ruby 2.0? ".)
O bien, 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 un caso Ruby y qué se puede hacer con él ".)
He empezado a utilizar:
a = "secondcase"
var_name = case a
when "firstcase" then "foo"
when "secondcase" then "bar"
end
puts var_name
>> "bar"
Ayuda a compacta el código en algunos casos.
Muchas respuestas geniales, pero pensé que agregaría un factoide. Si está intentando comparar objetos (Clases), asegúrese de tener un método de transporte espacial (no una broma) o entienda cómo se comparan.
Aquí hay una buena discusión sobre el tema http://www.skorks.com/2009/09/ruby-equality-and-object-comparison/
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, la caída suele ser 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, ya que no es posible permitir que ''a''
ejecute un bloque de código antes de pasar a ''b''
o ''c''
, pero en general, me parece lo suficientemente similar para ser útil de la misma manera.
Multi-valor cuando y sin valor caso:
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
Puedes escribir expresiones de casos de dos maneras diferentes en ruby.
- Similar a una serie de declaraciones "si"
- Especifique un objetivo al lado del caso y cada cláusula "cuándo" se compara con el objetivo.
1er camino
age = 20
case
when age >= 21
puts "display something"
when 1 == 0
puts "omg"
else
puts "default condition"
end
2ª vía
case params[:unknown]
when /Something/ then ''Nothing''
when /Something else/ then ''I dont know''
end
Puedes hacer esto de una manera más natural,
case expression
when condtion1
function
when condition2
function
else
function
end
Puedes 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
El case
de Ruby usará el operando de igualdad ===
para esto (gracias @JimDeville). Información adicional está disponible en " Operadores Ruby ". Esto también se puede hacer usando el ejemplo de @mmdemirbas (sin parámetro), solo este enfoque es más limpio para este tipo de casos.
Ruby usa el case
para escribir declaraciones de cambio.
Según los documentos de Ruby :
Las declaraciones de casos 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 primera cláusulawhen
para coincidir con la condición (o para evaluar la verdad booleana, si la condición es nula) "gana" y se ejecuta su stanza de código. El valor de la declaración de caso es el valor de la cláusulawhen
éxito, onil
si no existe tal cláusula.Una declaración de caso puede terminar con una cláusula
else
. Cada unawhen
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 este blog de Honeybadger describe Ruby Case;
Se puede utilizar con Ranges :
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!"
Se puede utilizar con Procs y Lambdas :
case 40
when -> (n) { n.to_s == "40" }
puts "lambdas!"
end
## => "lambdas"
Además, se puede utilizar con tus propias clases de partidos:
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
Se hace por case en ruby. También vea 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 The Ruby Programming Lanugage (1ª edición, O''Reilly), dice que la palabra clave " then
sigue a las cláusulas when
puede ser reemplazada por una nueva línea o punto y coma (como 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).
Se llama case
y funciona como cabría esperar, además de muchas más cosas divertidas por 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 un case
omitiendo el parámetro del case
inicial y simplemente escribiendo expresiones donde la primera coincidencia es lo que usted desea. querer.
case
when x.nil?
...
when (x.match /''^fn''/)
...
when (x.include? ''substring'')
...
when x.gsub(''o'', ''z'') == ''fnzrq''
...
when Time.now.tuesday?
...
end
Si está ansioso por saber cómo usar una condición OR en un caso de interruptor Ruby:
Entonces, en una declaración de 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 declaración del caso Ruby
case...when
comporta un poco inesperadamente al manejar clases. Esto se debe al hecho de que utiliza el operador ===
.
Ese operador funciona como se espera con los literales, pero no con las 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 ===
se ha definido de modo que devuelva 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 arreglar 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'')
end
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.
Ruby usa la expresión de case
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
utilizando el operador ===
. Por ejemplo, 1..5 === x
, y no x === 1..5
.
Esto permite sofisticado when
cláusulas 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 declaraciones de switch
en muchos otros idiomas, el case
de Ruby no tiene fall-through lo que no hay necesidad de terminar cada una con un break
. También puede especificar varias coincidencias en una sola cláusula when "foo", "bar"
como when "foo", "bar"
.
$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
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