Cómo escribir una declaración de cambio en Ruby

¿Cómo escribo un switch declaración en Ruby?

preguntado el 03 de junio de 09 a las 22:06

25 Respuestas

Ruby usa el case expresión preferiblemente.

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 el when cláusula con el objeto en el case cláusula usando el === operador. Por ejemplo, 1..5 === x, y no x === 1..5.

Esto permite sofisticados when cláusulas como se ve arriba. Se pueden probar rangos, clases y todo tipo de cosas en lugar de solo la igualdad.

Diferente a la switch declaraciones en muchos otros idiomas, Ruby case no tiene caer a través, por lo que no es necesario finalizar cada when con un break. También puede especificar varias coincidencias en una sola when cláusula como when "foo", "bar".

Respondido 04 Abr '18, 10:04

También puede hacer expresiones regulares en el argumento pasado: when / thisisregex / Proxima linea pone "Esta es la coincidencia encontrada nr. 1 # {$ 1}" end - Automático

También vale la pena señalar que puede acortar su código colocando el when y return declaración en la misma línea: when "foo" then "bar" - Alexander

Importante: Diferente a la switch declaraciones en muchos otros idiomas, Ruby case no tiene caer a través, por lo que no es necesario finalizar cada when con un break. - Janniks

Tantos votos positivos pero ni siquiera una mención de la palabra clave then. Consulte también las otras respuestas. - clint pachl

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 esperaba con literales, pero no con clases:

1 === 1           # => true
Fixnum === Fixnum # => false

Esto significa que si quieres 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 or number')
end

Se imprimirá "No es una cadena ni un número".

Afortunadamente, esto se resuelve fácilmente. La === se ha definido el operador para que devuelva true si lo usa con una clase y proporciona una instancia de esa clase como segundo operando:

Fixnum === 1 # => true

En resumen, el código anterior se puede solucionar 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 or number')
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 otras personas en mi misma situación.

Respondido 22 ago 19, 22:08

obj = 'hola'; caso obj; cuando "hola" pone al final "Es hola" - Sugumar Venkatesan

Tener el .class parte en es interesante notar, gracias. Por supuesto, este es un comportamiento completamente apropiado (aunque pude ver cómo podría ser un error común pensar que imprimiría It is a string) ... estás probando el clase de algún objeto arbitrario, no del objeto en sí. Así por ejemplo: case 'hello'.class when String then "String!" when Class then "Class!" else "Something else" end resulta en: "Class!" Esto funciona igual para 1.class, {}.class, etc. Dejar caer .class, obtenemos "String!" or "Something else" para estos diversos valores. - lindes

¡gracias por esto! esto es más elegante que mi solución que era usar "case obj.class.to_s" - russell fulton

sí, útil. gracias por salvarme 20 minutos de mi vida :) - Hari honor

Se hace usando case en Ruby. Ver también "Declaración de cambio"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 El lenguaje de programación Ruby (1.a edición, O'Reilly) en mi Kindle, dice el then palabra clave siguiendo el when las cláusulas se pueden reemplazar con una nueva línea o un punto y coma (como en el 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.)

Respondido el 09 de diciembre de 19 a las 19:12

when (-1.0/0.0)..-1 then "Epic fail" - andres grimm

Esta es la respuesta que utilicé, porque estoy definiendo una variable basada en los resultados de un cambio de caso. En lugar de decir type = #{score} cada línea, simplemente puedo copiar lo que hiciste. Mucho más elegante también me gustan mucho más las frases ingeniosas (si es posible) - onebree

Sé que esto no está relacionado con la esencia de la respuesta, pero 4 también es un cuadrado perfecto. - Nick Moore

Amo tanto a Ruby por permitirme poner una declaración de cambio en una variable como esa, menos desorden y va directo al grano: D - toro jaacko

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 "Cómo escribir una declaración de cambio en Ruby"ese kikito advierte.

respondido 25 nov., 19:23

Gracias, esto fue útil para tener múltiples opciones en una línea. Estuve tratando de usar or - sesenta y cuatro bits

En Ruby 2.0, también puede usar lambdas en case declaraciones, como sigue:

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 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 pueden usar procesos con declaraciones de casos 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 de Ruby y qué puede hacer con ella".)

contestado el 23 de mayo de 17 a las 12:05

Muchos lenguajes de programación, especialmente los derivados de C, tienen soporte para los llamados Interruptor Fallthrough. Estaba buscando la mejor manera de hacer lo mismo en Ruby y pensé que podría ser útil para otros:

En los lenguajes similares a C, la caída 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 'a' ejecutar un bloque de código antes de pasar a 'b' or 'c', pero en su mayor parte lo encuentro lo suficientemente similar como para ser útil de la misma manera.

contestado el 06 de mayo de 16 a las 02:05

Puede usar expresiones regulares, como buscar 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 usará el operando de igualdad === por esto (gracias @JimDeville). Hay información adicional disponible en "Operadores RubyEsto también se puede hacer usando el ejemplo de @mmdemirbas (sin parámetro), solo que este enfoque es más limpio para este tipo de casos.

contestado el 17 de mayo de 13 a las 04:05

Se llama case y funciona como es de esperar, además de muchas más cosas divertidas, cortesía de === que implementa 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 if / else arbitraria (es decir, incluso si las pruebas no involucran una variable común) con case dejando fuera la inicial case parámetro y simplemente escribiendo expresiones donde la primera coincidencia es la 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

Respondido el 30 de enero de 17 a las 22:01

Si está ansioso por saber cómo usar una condición OR en un caso de interruptor Ruby:

Entonces, en un case declaración, una , es el equivalente de || en una if .

case car
   when 'Maruti', 'Hyundai'
      # Code here
end

Ver "Cómo funciona una declaración de caso de Ruby y qué puede hacer con ella".

respondido 25 nov., 19:23

el formato de código no funciona en el artículo vinculado :-) - froderik

@froderik Está funcionando bien, solo tienes que comprobar el valor de la variable de car. - Manish Shrivastava

Ruby usa el case para escribir declaraciones de cambio.

Según el case documentación:

Las sentencias de caso consisten en una condición opcional, que está en la posición de un argumento para casey cero o más when cláusulas. El primero when cláusula para que coincida con 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 del éxito when cláusula, o nil si no existe tal cláusula.

Una declaración de caso puede terminar con un else cláusula. Cada when una declaración puede tener varios 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 de caso de Ruby: técnicas avanzadas"describe Ruby case;

Se puede utilizar 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!"

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 sus propias clases de coincidencias:

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

respondido 25 nov., 19:23

Dependiendo de su caso, podría preferir utilizar una serie de métodos.

Si hay una lista larga de whensy 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])

respondido 26 nov., 19:20

Como 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

Respondido 08 ago 15, 03:08

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 un 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

Respondido 08 ago 15, 03:08

porque no solo case some_string, when /\d/, (stuff), when /[a-zA-Z]/, (stuff), end (dónde , significa nueva línea) - tckmn

oh, y la primera parte ya está cubierta en esta respuesta, y muchas respuestas ya mencionan expresiones regulares. Francamente, esta respuesta no agrega nada nuevo, y estoy votando en contra y votando para eliminarla. - tckmn

@DoorknobofSnow Esto es para mostrar que puede usar la solución Regex y valores separados por comas en mayúsculas y minúsculas. No estoy seguro de por qué la solución le causa tanto dolor. - 123

Entonces, si obtuvieron una "F", una calificación legítima, ¿es su culpa que a su código le falte un caso? - mike graf

Me gusta el humor de esto y el hecho de que demuestra que puedes unir cadenas a un caso. - esmeril

Puedes escribir case expresiones de dos formas diferentes en Ruby:

  1. Similar a una serie de if declaraciones
  2. Especifique un objetivo junto al case y cada when la 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 bien:

case params[:unknown]
when /Something/ then 'Nothing'
when /Something else/ then 'I dont know'
end

respondido 26 nov., 19:20

Aunque su código podría responder a la pregunta, debe agregar al menos una breve descripción de lo que hace su código y cómo resuelve el problema inicial. - user1438038

Consideraré este consejo en el futuro. - Ysk

Puedes hacer esto de una manera más natural,

case expression
when condtion1
   function
when condition2
   function
else
   function
end

contestado el 26 de mayo de 16 a las 10:05

Muchas respuestas excelentes, pero pensé que agregaría un hecho. Si está intentando comparar objetos (clases), asegúrese de tener un método de nave espacial (no una broma) o de comprender cómo se comparan

"Comparación de objetos y igualdad de rubí"es una buena discusión sobre el tema.

respondido 25 nov., 19:23

Como referencia, el método de "nave espacial" es <=>, que se usa para devolver -1, 0, 1 o nulo dependiendo de si la comparación devuelve menor que, igual, mayor que o no comparable, respectivamente. Ruby Comparable La documentación del módulo lo explica. - el hombre de hojalata

Como se indica en muchas de las respuestas anteriores, el === El operador se utiliza debajo del capó en case/when Declaraciones.

Aquí hay información adicional sobre ese operador:

Operador de igualdad de casos: ===

Muchas de las clases integradas de Ruby, como String, Range y Regexp, proporcionan sus propias implementaciones de === operador, también conocido como "igualdad de mayúsculas y minúsculas", "triple igual" o "triple igual". 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ó. Generalmente, devuelve verdadero si el objeto de la derecha "pertenece a" o "es un miembro de" el objeto de la izquierda. Por ejemplo, puede usarse 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?.

Implementación de rango de ===

Cuando el === 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 los === 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 === se llamará al método, por lo que las posiciones de los operandos no son intercambiables.

Implementación de Regexp de ===

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 número entero, que es un valor verdadero en Ruby. Volveremos a esto pronto.

Respondido el 20 de junio de 20 a las 10:06

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

respondido 12 mar '16, 06:03

Es más útil si proporciona una explicación de por qué esta es la solución preferida y explica cómo funciona. Queremos educar, no solo proporcionar código. - el hombre de hojalata

$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

Ver "Ruby - si ... si no, caso, a menos que" para más información.

respondido 26 nov., 19:20

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 el código en algunos casos.

Respondido 08 ago 15, 03:08

Un código como este debería hacerse normalmente con un Hash, preferible a case declaración. - tom señor

Usar un hash sería más rápido cuando ese cambio se hace grande. - el hombre de hojalata

Es fundamental enfatizar la coma (,) en un when cláusula. Actúa como un || de una if declaración, es decir, hace una OR comparación y no una Y DE comparación entre las expresiones delimitadas del 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, sin embargo, el valor de retorno es "apple". ¿Por qué? Porque x tenía 3 años y desde ',`` acts as an||, it did not bother to evaluate the expressionx <2 '.

Podrías pensar que para realizar una Y DE, 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 (3 && x > 2) se evalúa como verdadero, y Ruby toma el valor Verdadero y lo compara con x con ===, lo cual no es cierto, ya que x es 3.

Hacer un && comparación, tendrás 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, ya sea que se use con poca frecuencia o no, no veo ninguna otra forma de adjuntar múltiples && expresiones para un dado when cláusula.

respondido 26 nov., 19:19

Esto no me parece un buen estilo de codificación. El uso de una sintaxis alternativa poco común confunde innecesariamente. ¿Por qué no usar normal if...elsif? Parece que está intentando mezclar una declaración de caso y una condición. ¿Por qué? Solo pon el condicional dentro el bloque cuando, por ejemplo. when 3; ( x < 2 ) ? 'apple' : 'orange' - sondra.kinsey

¿No admite expresiones regulares en su entorno? P.ej Shopify Editor de guiones (Abril de 2018):

[Error]: constante no inicializada RegExp

Una solución alternativa que sigue una combinación de métodos ya cubiertos anteriormente 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

solía ors en la declaración del método de clase ya que || tiene mayor precedencia que .include?.

Si aún prefiere usar ||, aunque or es preferible en este caso, puedes hacer esto en su lugar: (item.include? 'A') || .... Puedes probarlo en este repl.it.

Respondido 20 Jul 20, 10:07

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

Respondido el 28 de enero de 19 a las 06:01

Esto no funcionará; Palabras clave Ruby (p. Ej. case, when, end) distinguen entre mayúsculas y minúsculas y no pueden estar en mayúsculas como esta. - sondra.kinsey

NoMethodError (undefined method CASE 'para main: Object) `. Como dijo @ sondra.kinsey, no puedes usar mayúsculas. Ruby pensará que es una CONSTANTE. - el hombre de hojalata

La case El operador de declaración es como switch en los otros idiomas.

Esta es la sintaxis de switch...case 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 obtener más información, consulte la case documentación.

respondido 26 nov., 19:19

Prefiero usar case + que

number = 10

case number
when 1...8 then # ...
when 8...15 then # ...
when 15.. then # ...
end

Respondido 17 Feb 21, 19:02

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.