Comment écrire une switchdéclaration en Ruby?
Comment écrire une switchdéclaration en Ruby?
Réponses:
Ruby utilise plutôt l' caseexpression .
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 la whenclause avec l'objet dans la caseclause à l'aide de l' ===opérateur. Par exemple, 1..5 === xet non x === 1..5.
Cela permet des when clauses comme vu ci-dessus. Les plages, les classes et toutes sortes de choses peuvent être testées plutôt que simplement l'égalité.
Contrairement aux switchinstructions dans de nombreuses autres langues, Ruby casen'a pas d' interruption , il n'est donc pas nécessaire de terminer chacune whenpar un break. Vous pouvez également spécifier plusieurs correspondances dans une seule whenclause comme when "foo", "bar".
whenet returnsur la même ligne:when "foo" then "bar"
then. Veuillez également consulter les autres réponses.
case...whense comporte un peu de manière inattendue lors de la gestion 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 souhaitez effectuer une opération case ... whensur une classe d'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, cela est facilement résolu. L' ===opérateur a été défini de sorte qu'il renvoie truesi 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 .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'était la première page qui apparaissait, alors j'ai pensé que cela serait utile à d'autres dans ma même situation.
.classest intéressant de noter que le rôle est joué, merci. Bien sûr, c'est un comportement tout à fait approprié (bien que je puisse voir comment ce pourrait être une erreur courante de penser que cela s'imprimerait It is a string) ... vous testez la classe d'un objet arbitraire, pas l'objet lui-même. Ainsi, par exemple: les case 'hello'.class when String then "String!" when Class then "Class!" else "Something else" endrésultats dans: "Class!"Cela fonctionne même pour 1.class, {}.classetc. Dropping .class, nous obtenons "String!"ou "Something else"pour ces différentes valeurs.
Cela se fait en utilisant caseRuby. Voir également la « déclaration Switch » sur Wikipédia.
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
Sur la page 123 de The Ruby Programming Language (1st Edition, O'Reilly) sur mon Kindle, il est indiqué que le thenmot - clé suivant les whenclauses peut être remplacé par une nouvelle ligne ou un point-virgule (comme dans la if then elsesyntaxe). (Ruby 1.8 autorise également les deux points à la place de then, mais cette syntaxe n'est plus autorisée dans Ruby 1.9.)
when (-1.0/0.0)..-1 then "Epic fail"
type = #{score}chaque ligne, je peux simplement copier ce que vous avez fait. Beaucoup plus élégant j'aime aussi beaucoup mieux les one-liners (si possible)
Pour ajouter plus d'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 de " Comment écrire une instruction switch en Ruby " que kikito met en garde.
or
De nombreux langages de programmation, en particulier ceux dérivés de C, prennent en charge le soi-disant Switch Fallthrough . Je cherchais la meilleure façon de faire de même dans Ruby et j'ai pensé que cela pourrait être utile aux autres:
Dans les langages de type C, la chute ressemble 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;
}
Dans Ruby, la même chose peut être obtenue 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 strictement é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.
Dans Ruby 2.0, vous pouvez également utiliser des lambdas dans les caseinstructions, 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 à l'aide d'un Struct 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 "Les procs peuvent-ils être utilisés avec des instructions case dans 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 Ruby Case et ce que vous pouvez en faire ".)
Vous pouvez utiliser des expressions régulières, telles que rechercher un type de chaîne:
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's caseutilisera l'opérande d'égalité ===pour cela (merci @ JimDeville). Des informations supplémentaires sont disponibles sur " Opérateurs Ruby ". 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:
Ainsi, dans une casedéclaration, a ,est l'équivalent de ||dans une ifdéclaration.
case car
when 'Maruti', 'Hyundai'
# Code here
end
Voir " Fonctionnement d'une déclaration Ruby Case et ce que vous pouvez en faire ".
Il s'appelle caseet il fonctionne comme vous vous en doutez, en plus de beaucoup de choses amusantes grâce ===auxquelles les tests sont mis en œuvre.
case 5
when 5
puts 'yes'
else
puts 'else'
end
Maintenant, pour le plaisir:
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 s'avère 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) caseen omettant le caseparamètre initial et en écrivant simplement des expressions où la première correspondance correspond à ce que vous voulez.
case
when x.nil?
...
when (x.match /'^fn'/)
...
when (x.include? 'substring')
...
when x.gsub('o', 'z') == 'fnzrq'
...
when Time.now.tuesday?
...
end
Ruby utilise le casepour écrire des instructions switch.
Selon la casedocumentation:
Les instructions case se composent d'une condition facultative, qui est à la position d'un argument
caseet de zéro ou plusieurswhenclauses. La premièrewhenclause pour faire correspondre la condition (ou pour évaluer 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 lawhenclause réussie , ounils'il n'y en a pas.Une déclaration de cas peut se terminer par une
elseclause. Chaquewheninstruction 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 " l'énoncé de cas de Ruby - techniques avancées " 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"
Peut également être utilisé avec vos propres classes de correspondance:
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
Selon votre cas, vous pourriez préférer utiliser un hachage de méthodes.
S'il y a une longue liste de whens 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 puis d'appeler la méthode appropriée à partir du hachage 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])
Puisque switch caserenvoie toujours un seul objet, 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 sans valeur:
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 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
case some_string, when /\d/, (stuff), when /[a-zA-Z]/, (stuff), end(où ,signifie
Vous pouvez écrire des caseexpressions de deux manières différentes dans Ruby:
ifdéclarationscaseet chaque whenclause est comparée à la cible.age = 20
case
when age >= 21
puts "display something"
when 1 == 0
puts "omg"
else
puts "default condition"
end
ou:
case params[:unknown]
when /Something/ then 'Nothing'
when /Something else/ then 'I dont know'
end
Beaucoup de bonnes réponses mais je pensais que j'ajouterais un factoïde .. Si vous essayez de comparer des objets (classes) assurez-vous que vous avez une méthode de vaisseau spatial (pas une blague) ou comprenez comment ils sont comparés
" Ruby Equality And Object Comparison " est une bonne discussion sur le sujet.
<=>est utilisée pour renvoyer -1, 0, 1 ou zéro selon que la comparaison renvoie respectivement moins que, égal, supérieur ou non comparable. La documentation du module Comparable de Ruby l' explique.
Comme indiqué dans la plupart des réponses ci-dessus, l' ===opérateur est utilisé sous le capot sur case/ wheninstructions.
Voici des informations supplémentaires sur cet opérateur:
===De nombreuses classes intégrées de Ruby, telles que String, Range et Regexp, fournissent leurs propres implémentations de l' ===opérateur, également appelées «égalité de casse», «triple égal» ou «trois quals». Parce qu'il est implémenté différemment dans chaque classe, il se comportera différemment selon le type d'objet auquel il a été appelé. En général, elle renvoie vrai si l'objet de droite "appartient à" ou "est membre de" l'objet de gauche. Par exemple, il peut être utilisé pour tester si un objet est une instance d'une classe (ou l'une de ses sous-classes).
String === "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, telles que is_a?et instance_of?.
===Lorsque l' ===opérateur est appelé sur un objet de plage, il renvoie vrai 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
N'oubliez pas que l' ===opérateur appelle la ===méthode de l'objet de gauche. (1..4) === 3Est donc é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ée, de sorte que 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/ === "practice zazen today" # Output: => true
# is similar to
"practice zazen today"=~ /zen/
La seule différence pertinente entre les deux exemples ci-dessus est que, en cas de correspondance, ===renvoie true et =~renvoie un entier, qui est une valeur véridique dans Ruby. Nous y reviendrons bientôt.
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
$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
Voir " Ruby - si ... sinon, cas, sauf " pour plus d'informations.
J'ai commencé à utiliser:
a = "secondcase"
var_name = case a
when "firstcase" then "foo"
when "secondcase" then "bar"
end
puts var_name
>> "bar"
Il aide à compacter du code dans certains cas.
Hash, plutôt que d'une caseinstruction.
Pas de prise en charge des expressions régulières dans votre environnement? Par exemple, Shopify Script Editor (avril 2018):
[Erreur]: RegExp constante non initialisée
Une solution de contournement suivant une combinaison de méthodes déjà décrites précédemment 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é ors dans l'instruction de méthode de classe depuis ||a une priorité plus élevée que
.include?. Si vous êtes un rubis-nazi , imaginez s'il vous plaît que j'ai utilisé cela à la (item.include? 'A') || ...place. test repl.it.
Il est essentiel de souligner la virgule ( ,) dans une whenclause. Il agit comme ||d'une ifdéclaration, qui est, il fait un OU comparaison et non une ET comparaison entre les expressions délimitées de la whenclause. Voir l'énoncé de cas suivant:
x = 3
case x
when 3, x < 2 then 'apple'
when 3, x > 2 then 'orange'
end
=> "apple"
xn'est pas inférieur à 2, mais la valeur de retour est "apple". Pourquoi? Parce que xc'était 3 et depuis ',`` acts as an|| , it did not bother to evaluate the expressionx <2 '.
Vous pourriez penser que pour effectuer un ET , vous pouvez faire quelque chose comme ceci ci-dessous, mais cela ne fonctionne pas:
case x
when (3 && x < 2) then 'apple'
when (3 && x > 2) then 'orange'
end
=> nil
Cela ne fonctionne pas, car (3 && x > 2)il a la valeur true, et Ruby prend la valeur True et la compare à xavec ===, ce qui n'est pas vrai, car elle xvaut 3.
Pour faire une &&comparaison, vous devrez traiter casecomme un bloc if/ else:
case
when x == 3 && x < 2 then 'apple'
when x == 3 && x > 2 then 'orange'
end
Dans le livre Ruby Programming Language, Matz dit que cette dernière forme est la forme simple (et rarement utilisée), qui n'est rien d'autre qu'une syntaxe alternative pour if/ elsif/ else. Cependant, qu'il soit rarement utilisé ou non, je ne vois pas d'autre moyen d'attacher plusieurs &&expressions pour une donnéewhen clause .
if...elsif? Il semble que vous essayez de mélanger une déclaration de cas et une condition. Pourquoi? Mettez simplement le conditionnel dans le bloc when, par exemple. when 3; ( x < 2 ) ? 'apple' : 'orange'
Nous pouvons écrire une instruction switch pour plusieurs conditions.
Par exemple,
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
case, when, end) Sont sensibles à la casse et ne peuvent pas être en majuscules comme celui - ci.
NoMethodError (undefined method CASE 'pour main: Object) `. Comme l'a dit @ sondra.kinsey, vous ne pouvez pas utiliser de majuscules. Ruby pensera que c'est une constante.
L' caseopérateur de déclaration est comme switchdans les autres langues.
Voici la syntaxe de switch...caseen C:
switch (expression)
{
case constant1:
// statements
break;
case constant2:
// statements
break;
.
.
.
default:
// default statements
}
Voici la syntaxe de case...whenRuby:
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
Par exemple:
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
Pour plus d'informations, consultez la casedocumentation.