Déclaration de cas avec plusieurs valeurs dans chaque bloc «quand»


315

La meilleure façon de décrire ce que je recherche est de vous montrer le code qui a échoué jusqu'à présent:

case car
  when ['honda', 'acura'].include?(car)
    # code
  when 'toyota' || 'lexus'
    # code
end

J'ai environ 4 ou 5 whensituations différentes qui devraient être déclenchées par environ 50 valeurs différentes possibles de car. Existe-t-il un moyen de le faire avec des caseblocs ou dois-je essayer un ifbloc massif ?

Réponses:


669

Dans une caseinstruction, a ,est l'équivalent de ||dans une ifinstruction.

case car
   when 'toyota', 'lexus'
      # code
end

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


1
Ce lien a un meilleur résumé des déclarations de cas dans Ruby (et il inclut également des exemples de la syntaxe regexp et splat).
rsenna

Je ne sais pas pourquoi, mais cette situation étrange se produit: Quand j'écris ceci: when "toyota", "lexus", je reçois: unexpected tSTRING_BEG, expecting keyword_do or '{' or '(' (SyntaxError). Cependant, quand j'écris ceci: when "toyota","lexus"ça marche. La seule différence est un espace après une virgule.
Furkan Ayhan

@FurkanAyhan C'est étrange. Je suis allé de l'avant et j'ai testé le code juste pour m'assurer et cela fonctionne. Je suppose qu'il y a quelque chose d'autre dans votre code qui fait une erreur comme ça. Est-il possible que vous ayez oublié de fermer une chaîne quelque part ou quelque chose comme ça?
Charles Caldwell

1
bien, cela fonctionne, mais comme ruby ​​se concentre sur la facilité du programmeur, je me demande pourquoi il ne prend pas en charge la norme || ou ou'? C'est un peu déroutant
Zia Ul Rehman Mughal

2
Ruby ne prend pas en charge orou ||ici car le whenprend une série d'expressions séparées par des virgules à sa droite, pas un seul identifiant. Pour cette raison, si vous l'aviez when a or b, il n'est pas clair si cela doit être pris comme l'équivalent de when a, bou when (a or b), ce dernier évaluant l'expression en a or bpremier avant de la jeter dans le quand. Il est plus surprenant et moins facile à gérer pour le langage d'avoir des jetons qui changent le comportement en fonction du contexte, et alors vous ne seriez pas en mesure d'utiliser une vraie orexpression du côté droit d'un moment.
Taywee

99

Vous pourriez profiter de la syntaxe "splat" ou d'aplatissement de ruby.

Cela rend les whenclauses envahissantes - vous avez environ 10 valeurs à tester par branche si je comprends bien - un peu plus lisible à mon avis. De plus, vous pouvez modifier les valeurs à tester lors de l'exécution. Par exemple:

honda  = ['honda', 'acura', 'civic', 'element', 'fit', ...]
toyota = ['toyota', 'lexus', 'tercel', 'rx', 'yaris', ...]
...

if include_concept_cars
  honda += ['ev-ster', 'concept c', 'concept s', ...]
  ...
end

case car
when *toyota
  # Do something for Toyota cars
when *honda
  # Do something for Honda cars
...
end

Une autre approche courante consisterait à utiliser un hachage comme table de répartition, avec des clés pour chaque valeur de caret des valeurs qui sont des objets appelables encapsulant le code que vous souhaitez exécuter.


C'est ce que j'ai fini par utiliser, même si je me sens mal de retirer la coche de quelqu'un: D
Nick

Solution brillante pour les longues whenlignes. Merci d'avoir partagé.
Pistos

0

Une autre bonne façon de mettre votre logique dans les données est quelque chose comme ceci:

# Initialization.
CAR_TYPES = {
  foo_type: ['honda', 'acura', 'mercedes'],
  bar_type: ['toyota', 'lexus']
  # More...
}
@type_for_name = {}
CAR_TYPES.each { |type, names| names.each { |name| @type_for_name[type] = name } }

case @type_for_name[car]
when :foo_type
  # do foo things
when :bar_type
  # do bar things
end

Je ne veux pas être impoli, mais j'ai voté contre parce que c'est moins efficace à la fois dans le temps et dans l'espace. Il est également plus complexe et moins lisible que les deux autres réponses. Quel serait l'avantage d'utiliser cette méthode?
Nick

Il met toute votre classification en un seul objet. Vous pouvez maintenant faire des choses avec cet objet, comme le sérialiser et l'envoyer à quelqu'un d'autre pour expliquer votre logique, ou le stocker dans une base de données et permettre aux gens de le modifier. (La logique changera très bientôt lorsque de nouveaux modèles de voitures sortiront, non?) Vous pourriez rechercher "piloté par table".
Hew Wolff

YAGNI ("Vous n'en aurez pas besoin") peut s'appliquer ici. La conception sacrifie l'efficacité temps / espace et la lisibilité pour un scénario qui pourrait exister dans le futur mais qui n'existe pas encore. Le coût est payé maintenant, mais la récompense peut ne jamais être récoltée.
Nick
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.