Istruzione case con più valori in ciascun blocco 'when'


315

Il modo migliore per descrivere ciò che sto cercando è mostrarti il ​​codice fallito che ho provato finora:

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

Ho circa 4 o 5 diverse whensituazioni che dovrebbero essere innescate da circa 50 diversi possibili valori di car. C'è un modo per farlo con i caseblocchi o dovrei provare un ifblocco enorme ?

Risposte:


669

In caseun'istruzione, a ,è l'equivalente di ||in ifun'istruzione.

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

Alcune altre cose che puoi fare con una dichiarazione del caso Ruby


1
Questo link ha un miglior riassunto delle dichiarazioni dei casi in Ruby (e include anche esempi della sintassi regexp e splat).
rsenna,

Non so perché, ma questa strana situazione si verifica: Quando scrivo questo: when "toyota", "lexus", ottengo: unexpected tSTRING_BEG, expecting keyword_do or '{' or '(' (SyntaxError). Tuttavia, quando scrivo questo when "toyota","lexus":, funziona. L'unica differenza è uno spazio dopo la virgola.
Furkan Ayhan,

@FurkanAyhan È strano. Sono andato avanti e ho testato il codice solo per essere sicuro e funziona. Suppongo che ci sia qualcos'altro nel tuo codice che lo sta rendendo un errore del genere. È possibile che ti sei dimenticato di chiudere una stringa da qualche parte o qualcosa del genere?
Charles Caldwell,

1
bene, questo funziona, ma come ruby ​​si concentra sulla facilità del programmatore, mi chiedo perché non supporti lo standard || o o'? Questo è un po 'di confusione
Zia Ul Rehman Mughal

2
Ruby non supporta oro ||qui perché whenprende una serie di espressioni separate da virgole a destra, non un singolo identificatore. Per questo motivo, se lo hai fatto when a or b, non è chiaro se questo debba essere preso come l'equivalente di when a, bo when (a or b), quest'ultimo dei quali valuta l'espressione a or bprima di gettarla nel quando. È più sorprendente e meno facile da gestire per il linguaggio avere token che cambiano il comportamento in base al contesto, e quindi non saresti in grado di usare orun'espressione reale sul lato destro di un momento.
Taywee,

99

Potresti trarre vantaggio dalla "splat" di Ruby o dalla sintassi piatta.

Questo rende le whenclausole invase - hai circa 10 valori da testare per ramo se ho capito bene - un po 'più leggibile secondo me. Inoltre, è possibile modificare i valori da testare in fase di esecuzione. Per esempio:

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

Un altro approccio comune sarebbe quello di utilizzare un hash come tabella di invio, con chiavi per ciascun valore care valori che sono un oggetto richiamabile che incapsula il codice che si desidera eseguire.


Questo è quello che ho finito per usare, anche se mi sento male a togliere il segno di spunta di qualcuno: D
Nick

Soluzione brillante per le lunghe whenfile. Grazie per la condivisione.
Pistos

0

Un altro bel modo per inserire la tua logica nei dati è qualcosa del genere:

# 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

Non intendo essere scortese, ma ho effettuato il downgrade perché è meno efficiente sia nel tempo che nello spazio. È anche più complesso e meno leggibile rispetto alle altre due risposte. Quale sarebbe il vantaggio di utilizzare questo metodo?
Nick,

Mette tutta la tua classificazione in un oggetto. Ora puoi fare cose con quell'oggetto, come serializzarlo e inviarlo a qualcun altro per spiegare la tua logica, o memorizzarlo in un database e consentire alle persone di modificarlo. (La logica cambierà molto presto quando usciranno nuovi modelli di auto, giusto?) Potresti cercare "guidato da tavolo".
Hew Wolff,

YAGNI ("Non ne avrai bisogno") potrebbe essere applicato qui. Il design sacrifica l'efficienza tempo / spazio e la leggibilità per uno scenario che potrebbe esistere in futuro ma che non esiste ancora. Il costo è ora pagato, ma la ricompensa potrebbe non essere mai raccolta.
Nick,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.