Comment écrire une déclaration de changement dans Ruby?

Comment puis-je écrire une déclaration de changement dans Ruby?

Ruby utilise l’ expression de case 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 Ssortingng "You passed a ssortingng" else "You gave me #{x} -- I have no idea what to do with that." end 

Ruby compare l’object dans la clause when avec l’object dans la clause case utilisant l’opérateur === . Par exemple, 1..5 === x , et non x === 1..5 .

Cela permet des clauses sophistiquées comme vu ci-dessus. Les gammes, les classes et toutes sortes de choses peuvent être testées plutôt que simplement l’égalité.

Contrairement aux instructions de switch dans de nombreux autres langages, le case de Ruby n’a pas de retentissement , il n’est donc pas nécessaire de terminer chaque when avec une break . Vous pouvez également spécifier plusieurs correspondances dans une clause unique when "foo", "bar" .

case...when se comporte un peu inopinément lors de la manipulation des classes. Cela est dû au fait qu’il utilise l’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 object, cela ne fonctionnera pas:

 obj = 'hello' case obj.class when Ssortingng print('It is a ssortingng') when Fixnum print('It is a number') else print('It is not a ssortingng') end 

Va imprimer “Ce n’est pas une chaîne”.

Heureusement, cela est facilement résolu. L’opérateur === a été défini pour qu’il renvoie true si vous l’utilisez avec une classe et fournissez une instance de cette classe en tant que second opérande:

 Fixnum === 1 # => true 

En bref, le code ci-dessus peut être corrigé en supprimant la .class :

 obj = 'hello' case obj # was case obj.class when Ssortingng print('It is a ssortingng') when Fixnum print('It is a number') else print('It is not a ssortingng') end 

J’ai rencontré ce problème aujourd’hui en cherchant une réponse, et c’était la première page apparue, alors j’ai pensé que ce serait utile pour les autres dans la même situation.

Cela se fait par cas en Ruby. Voir aussi cet article sur Wikipedia .

Cité:

 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 

À la page 123 (J’utilise Kindle) de The Ruby Programming Lanugage (1ère édition, O’Reilly), il est dit que le mot clé then suit les clauses when peut être remplacé par newline ou semicolon (comme dans la syntaxe if then else ). (Ruby 1.8 permet également un deux-points à la place de… mais cette syntaxe n’est plus autorisée dans Ruby 1.9.)

cas … quand

Pour append 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, soyez conscient du problème que kikito met en garde.

Dans Ruby 2.0, vous pouvez également utiliser lambdas dans les instructions de 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 vos propres comparateurs en utilisant facilement une structure avec une personnalisation ===

 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 ” Peut-on utiliser procs avec des instructions de cas dans Ruby 2.0? “.)

Ou avec un cours complet:

 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 Ruby et ce que vous pouvez en faire “).

De nombreux langages de programmation, en particulier ceux dérivés du langage C, prennent en charge le soi-disant Switch Fallthrough . Je cherchais la meilleure façon de faire la même chose dans Ruby et pensais que cela pourrait être utile à d’autres:

En langage C, les langages ressemblent généralement à ceci:

 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, la même chose peut être réalisée de la manière suivante:

 case expression when 'a', 'b', 'c' # Do something for a, b or c when 'd', 'e' # Do something else for d or e end 

Ce n’est pas ssortingctement équivalent, car il n’est pas possible de laisser 'a' exécuter un bloc de code avant de passer à 'b' ou 'c' , mais pour la plupart je le trouve assez similaire pour être utile de la même manière.

Vous pouvez utiliser des expressions régulières, telles que trouver un type de chaîne:

 case foo when /^(true|false)$/ puts "Given ssortingng is boolean" when /^[0-9]+$/ puts "Given ssortingng is integer" when /^[0-9\.]+$/ puts "Given ssortingng is float" else puts "Given ssortingng is probably ssortingng" end 

Le case de Ruby utilisera l’opérande d’égalité === pour cela (merci @JimDeville). Des informations supplémentaires sont disponibles chez ” Ruby Operators “. Cela peut également être fait en utilisant l’exemple @mmdemirbas (sans paramètre), seule cette approche est plus propre pour ces types de cas.

Si vous êtes impatient de savoir comment utiliser une condition OU dans un boîtier de commutateur Ruby:

Donc, dans un case , a est l’équivalent de || dans une déclaration if .

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

Beaucoup d’autres choses que vous pouvez faire avec une déclaration de cas Ruby

Il s’appelle case et fonctionne comme prévu, ainsi que beaucoup plus de choses amusantes grâce à === qui implémente les tests.

 case 5 when 5 puts 'yes' else puts 'else' end 

Maintenant pour s’amuser:

 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 

Et il se trouve que vous pouvez également remplacer une chaîne if / else arbitraire (c’est-à-dire, même si les tests n’impliquent pas une variable commune) avec case en omettant le paramètre de case initial et en écrivant simplement des expressions où la première vouloir.

 case when x.nil? ... when (x.match /'^fn'/) ... when (x.include? 'subssortingng') ... when x.gsub('o', 'z') == 'fnzrq' ... when Time.now.tuesday? ... end 

Comme le switch case retourne toujours un seul object, nous pouvons directement imprimer son résultat:

 puts case a when 0 "It's zero" when 1 "It's one" end 

Cas à valeurs multiples et valeur nulle:

 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 

Et une solution d’ expression régulière ici:

 print "Enter a ssortingng: " some_ssortingng = gets.chomp case when some_ssortingng.match(/\d/) puts 'Ssortingng has numbers' when some_ssortingng.match(/[a-zA-Z]/) puts 'Ssortingng has letters' else puts 'Ssortingng has no numbers or letters' end 

Selon votre cas, vous pourriez préférer utiliser un hachage de méthodes.

S’il y a une longue liste de when et que chacun d’eux a une valeur concrète à comparer (pas un intervalle), il sera plus efficace de déclarer un hachage de méthodes et d’appeler la méthode correspondante du hash comme ça.

 # 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]) 

Ruby utilise le case pour écrire des instructions de commutation.

Selon les Ruby Docs :

Les instructions de cas sont constituées d’une condition facultative, qui se trouve dans la position d’un argument par rapport à la case , et de zéro ou plusieurs when clauses. La première clause when qui correspond à la condition (ou à l’évaluation de la vérité booléenne, si la condition est nulle) «gagne» et sa strophe de code est exécutée. La valeur de l’instruction case est la valeur de la clause when , ou nil s’il n’y en a pas.

Une instruction de cas peut se terminer par une clause else . Chaque when qu’une instruction peut avoir plusieurs valeurs candidates, séparées par des virgules.

Exemple:

 case x when 1,2,3 puts "1, 2, or 3" when 10 puts "10" else puts "Some other number" end 

Version plus courte:

 case x when 1,2,3 then puts "1, 2, or 3" when 10 then puts "10" else puts "Some other number" end 

Et comme ce blog de Honeybadger décrit Ruby Case;

Peut être utilisé avec des gammes :

 case 5 when (1..10) puts "case statements match inclusion in a range" end ## => "case statements match inclusion in a range" 

Peut être utilisé avec Regex :

 case "FOOBAR" when /BAR$/ puts "they can match regular expressions!" end ## => "they can match regular expressions!" 

Peut être utilisé avec Procs et Lambdas :

 case 40 when -> (n) { n.to_s == "40" } puts "lambdas!" end ## => "lambdas" 

En outre, peuvent être utilisés avec vos propres classes de match:

 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 

Vous pouvez écrire des expressions de cas de deux manières différentes dans Ruby.

  1. Semblable à une série de “si” déclarations
  2. Spécifiez une cible à côté du cas et chaque clause “when” est comparée à la cible.

1ère voie

 age = 20 case when age >= 21 puts "display something" when 1 == 0 puts "omg" else puts "default condition" end 

2ème voie

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

Beaucoup de bonnes réponses, mais je pensais append un factoid. Si vous essayez de comparer des objects (Classes), assurez-vous d’avoir une méthode de vaisseau spatial (pas une blague) ou de comprendre comment ils sont comparés.

Voici une bonne discussion sur le sujet http://www.skorks.com/2009/09/ruby-equality-and-object-comparison/

Vous pouvez faire comme ça de manière plus naturelle,

 case expression when condtion1 function when condition2 function else function end 
 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 

Comme indiqué dans la plupart des réponses ci-dessus, l’opérateur === est utilisé sous le capot des instructions case / when.

Voici quelques informations supplémentaires sur cet opérateur.

Opérateur d’égalité de cas: ===

Bon nombre des classes intégrées de Ruby, telles que Ssortingng, Range et Regexp, fournissent leurs propres implémentations de l’opérateur ===, également connu sous le nom d’égalité de casse, sortingple equals ou threequals. Comme il est implémenté différemment dans chaque classe, il se comportera différemment selon le type d’object sur lequel il a été appelé. Généralement, il renvoie true si l’object à droite “appartient à” ou “est membre de” l’object à gauche. Par exemple, il peut être utilisé pour tester si un object est une instance d’une classe (ou de l’une de ses sous-classes).

 Ssortingng === "zen" # Output: => true Range === (1..2) # Output: => true Array === [1,2,3] # Output: => true Integer === 2 # Output: => true 

Le même résultat peut être obtenu avec d’autres méthodes qui sont probablement les mieux adaptées au travail, comme is_a? et instance_of?.

Implémentation de la plage de ===

Lorsque l’opérateur === est appelé sur un object de plage, il renvoie true si la valeur de droite se situe dans la plage de gauche.

 (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 

Rappelez-vous que l’opérateur === appelle la méthode === de l’object de gauche. Donc (1..4) === 3 est équivalent à (1..4). === 3. En d’autres termes, la classe de l’opérande de gauche définira quelle implémentation de la méthode === sera appelé, donc les positions des opérandes ne sont pas interchangeables.

Regexp Implémentation de ===

Renvoie true si la chaîne de droite correspond à l’expression régulière de gauche. / zen / === “pratique zazen aujourd’hui” # Sortie: => true # est similaire à “pratique zazen aujourd’hui” = ~ / zen /

La seule différence pertinente entre les deux exemples ci-dessus est que, quand il y a correspondance, === renvoie true et = ~ renvoie un entier, ce qui est une valeur de vérité dans Ruby. Nous y reviendrons bientôt.

 $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 

référence => https://www.tutorialspoint.com/ruby/ruby_if_else.htm

J’ai commencé à utiliser:

 a = "secondcase" var_name = case a when "firstcase" then "foo" when "secondcase" then "bar" end puts var_name >> "bar" 

Cela aide à compacter le code dans certains cas.

Pas de support pour les expressions régulières dans votre environnement? Par exemple, Shopify Script Editor (avril 2018):

[Erreur]: constante non initialisée RegExp

Une solution de contournement suite à une combinaison de méthodes déjà abordées ici et ici :

 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 

J’ai utilisé or s dans la déclaration de méthode de classe depuis || a plus de priorité que .include? . Si vous êtes un rbuy-nazi , veuillez imaginer que j’ai utilisé ceci (item.include? 'A') || ... (item.include? 'A') || ... place. test de repl.it