Comment écrire une switch
déclaration en Ruby?
Comment écrire une switch
déclaration en Ruby?
Réponses:
Ruby utilise plutôt l' case
expression .
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 when
clause avec l'objet dans la case
clause à l'aide de l' ===
opérateur. Par exemple, 1..5 === x
et 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 switch
instructions dans de nombreuses autres langues, Ruby case
n'a pas d' interruption , il n'est donc pas nécessaire de terminer chacune when
par un break
. Vous pouvez également spécifier plusieurs correspondances dans une seule when
clause comme when "foo", "bar"
.
when
et return
sur la même ligne:when "foo" then "bar"
then
. Veuillez également consulter les autres réponses.
case...when
se 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 ... when
sur 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 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 .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.
.class
est 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" end
résultats dans: "Class!"
Cela fonctionne même pour 1.class
, {}.class
etc. Dropping .class
, nous obtenons "String!"
ou "Something else"
pour ces différentes valeurs.
Cela se fait en utilisant case
Ruby. 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 then
mot - clé suivant les when
clauses peut être remplacé par une nouvelle ligne ou un point-virgule (comme dans la if then else
syntaxe). (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 case
instructions, 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 case
utilisera 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 case
déclaration, a ,
est l'équivalent de ||
dans une if
dé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 case
et 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) case
en omettant le case
paramè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 case
pour écrire des instructions switch.
Selon la case
documentation:
Les instructions case se composent d'une condition facultative, qui est à la position d'un argument
case
et de zéro ou plusieurswhen
clauses. La premièrewhen
clause 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 lawhen
clause réussie , ounil
s'il n'y en a pas.Une déclaration de cas peut se terminer par une
else
clause. Chaquewhen
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 " 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 when
s 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 case
renvoie 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 case
expressions de deux manières différentes dans Ruby:
if
déclarationscase
et chaque when
clause 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
/ when
instructions.
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) === 3
Est 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 case
instruction.
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é or
s 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 when
clause. Il agit comme ||
d'une if
déclaration, qui est, il fait un OU comparaison et non une ET comparaison entre les expressions délimitées de la when
clause. Voir l'énoncé de cas suivant:
x = 3
case x
when 3, x < 2 then 'apple'
when 3, x > 2 then 'orange'
end
=> "apple"
x
n'est pas inférieur à 2, mais la valeur de retour est "apple"
. Pourquoi? Parce que x
c'était 3 et depuis ',`` acts as an
|| , it did not bother to evaluate the expression
x <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 à x
avec ===
, ce qui n'est pas vrai, car elle x
vaut 3.
Pour faire une &&
comparaison, vous devrez traiter case
comme 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' case
opérateur de déclaration est comme switch
dans les autres langues.
Voici la syntaxe de switch...case
en C:
switch (expression)
{
case constant1:
// statements
break;
case constant2:
// statements
break;
.
.
.
default:
// default statements
}
Voici la syntaxe de case...when
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
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 case
documentation.