2180 votes

Comment écrire une instruction switch en Ruby

Comment rédiger un switch en Ruby ?

2803voto

Chuck Points 138930

Ruby utilise le case expression à la place.

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 compare l'objet dans le when avec l'objet dans la clause case en utilisant la clause === opérateur. Par exemple, 1..5 === x et non x === 1..5 .

Cela permet de sophistiquer when comme indiqué ci-dessus. Il est possible de tester des plages, des classes et toutes sortes de choses, et pas seulement l'égalité.

Contrairement à switch dans beaucoup d'autres langages, les instructions de Ruby case n'a pas passage à travers Il n'est donc pas nécessaire de terminer chaque when avec un break . Vous pouvez également spécifier plusieurs correspondances dans un seul when comme when "foo", "bar" .

16 votes

Vous pouvez aussi faire du regex sur l'argument passé : quand /thisisregex/ ligne suivante met "C'est la correspondance trouvée nr. 1 #{$1}" end

9 votes

Il convient également de noter que vous pouvez raccourcir votre code en plaçant la balise when y return sur la même ligne : when "foo" then "bar"

12 votes

Important : Contrairement à switch dans beaucoup d'autres langages, les instructions de Ruby case n'a PAS passage à travers Il n'est donc pas nécessaire de terminer chaque when avec un break .

460voto

kikito Points 23229

case...when se comporte de manière un peu inattendue lors de la manipulation des classes. Cela est dû au fait qu'il utilise l'attribut === opérateur.

Cet opérateur fonctionne comme prévu avec les littéraux, mais pas avec les classes :

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

Cela signifie que si vous voulez faire un case ... when sur la classe d'un objet, cela ne fonctionnera pas :

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

Imprime "Ce n'est pas une chaîne ou un nombre".

Heureusement, ce problème est facilement résolu. Le site === a été défini de manière à ce qu'il renvoie true si vous l'utilisez avec une classe et fournissez une instance de cette classe comme deuxième opérande :

Fixnum === 1 # => true

En bref, le code ci-dessus peut être corrigé en supprimant l'option .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

J'ai rencontré ce problème aujourd'hui en cherchant une réponse, et c'est la première page qui est apparue, alors j'ai pensé que cela pourrait être utile à d'autres personnes dans la même situation que moi.

0 votes

Obj='hello';case obj ; when 'hello' then puts "It's hello" end

0 votes

Avoir le .class est intéressant à noter, merci. Bien sûr, il s'agit d'un comportement tout à fait approprié (bien que je puisse voir comment il pourrait être une erreur commune de penser que ce serait imprimé ). It is a string )... vous testez le classe d'un objet arbitraire, et non l'objet lui-même. Donc, par exemple : case 'hello'.class when String then "String!" when Class then "Class!" else "Something else" end résultats dans : "Class!" Cela fonctionne de la même manière pour 1.class , {}.class etc. Abandon de .class on obtient "String!" o "Something else" pour ces différentes valeurs.

1 votes

Merci pour cela ! c'est plus élégant que ma solution qui consistait à utiliser "case obj.class.to_s".

229voto

動靜能量 Points 33008

Cela se fait en utilisant case en Ruby. Voir aussi " Déclaration de commutation "sur Wikipedia.

Citée :

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 autre exemple :

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

Aux alentours de la page 123 de Le langage de programmation Ruby (1ère édition, O'Reilly) sur mon Kindle, il est dit que le then après le mot-clé when peuvent être remplacées par un saut de ligne ou un point-virgule (comme dans la clause if then else ). (Ruby 1.8 autorise également l'utilisation de deux points à la place de then mais cette syntaxe n'est plus autorisée dans Ruby 1.9).

41 votes

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

1 votes

C'est la réponse que j'ai utilisée, car je définis une variable basée sur les résultats d'un switch de cas. Plutôt que de dire type = #{score} chaque ligne, je peux simplement copier ce que vous avez fait. C'est beaucoup plus élégant. J'aime aussi beaucoup mieux les phrases d'une seule ligne (si possible).

1 votes

Je sais que ça n'a rien à voir avec l'essence de la réponse, mais 4 est aussi un carré parfait.

110voto

mmdemirbas Points 3205

Cas... quand

Pour ajouter d'autres exemples à La réponse de Chuck :

Avec paramètre :

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

Sans paramètre :

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

S'il vous plaît, faites attention à " Comment écrire une instruction switch en Ruby " dont Kikito nous met en garde.

0 votes

Merci, c'était utile pour avoir plusieurs options sur une ligne. J'avais essayé d'utiliser or

80voto

Jim Lim Points 4981

En Ruby 2.0, vous pouvez également utiliser les lambdas dans les éléments suivants case comme suit :

is_even = ->(x) { x % 2 == 0 }

case number
when 0 then puts 'zero'
when is_even then puts 'even'
else puts 'odd'
end

Vous pouvez également créer facilement vos propres comparateurs en utilisant une structure avec une fonction personnalisée ===

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

(Exemple tiré de " Les procs peuvent-ils être utilisés avec les instructions case en Ruby 2.0 ? ".)

Ou, avec une classe complète :

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

(Exemple tiré de " Comment fonctionne une déclaration de cas en Ruby et ce que vous pouvez en faire ".)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X