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.)
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 plusieurswhen
clauses. La première clausewhen
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 clausewhen
, ounil
s’il n’y en a pas.Une instruction de cas peut se terminer par une clause
else
. Chaquewhen
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.
age = 20 case when age >= 21 puts "display something" when 1 == 0 puts "omg" else puts "default condition" end
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.
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?.
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.
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