Instrukcja case z wieloma wartościami w każdym bloku „when”

314

Najlepszym sposobem, w jaki mogę opisać to, czego szukam, jest pokazanie nieudanego kodu, którego do tej pory próbowałem:

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

Mam około 4 lub 5 różnych whensytuacji, które powinny być wywołane przez około 50 różnych możliwych wartości car. Czy można to zrobić za pomocą casebloków, czy powinienem wypróbować masywny ifblok?

Nacięcie
źródło

Odpowiedzi:

669

W casezestawieniu, na ,to odpowiednik ||w ifoświadczeniu.

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

Kilka innych rzeczy, które możesz zrobić za pomocą instrukcji Ruby

Charles Caldwell
źródło
1
Ten link ma lepsze podsumowanie instrukcji case w Ruby (zawiera także przykłady składni wyrażeń regularnych i splat).
rsenna
Nie wiem dlaczego, ale ta dziwna sytuacja dzieje: Gdy piszę te słowa: when "toyota", "lexus"otrzymuję: unexpected tSTRING_BEG, expecting keyword_do or '{' or '(' (SyntaxError). Kiedy jednak to piszę: when "toyota","lexus"działa. Jedyną różnicą jest spacja po przecinku.
Furkan Ayhan
@FurkanAyhan To dziwne. Poszedłem do przodu i przetestowałem kod, aby się upewnić, że działa. Domyślam się, że w twoim kodzie dzieje się coś innego, co powoduje taki błąd. Czy to możliwe, że zapomniałeś gdzieś zamknąć sznurek lub coś takiego?
Charles Caldwell,
1
cóż, to działa, ale ponieważ Ruby koncentruje się na łatwości programisty, zastanawiam się, dlaczego nie obsługuje standardu || albo albo'? To trochę mylące
Zia Ul Rehman Mughal
2
Ruby nie obsługuje orlub ||tutaj, ponieważ whenbierze po prawej stronie serię wyrażeń oddzielonych przecinkami, a nie pojedynczy identyfikator. Z tego powodu, jeśli tak when a or b, nie jest jasne, czy należy to traktować jako ekwiwalent when a, blub when (a or b), przy czym ten ostatni ocenia wyrażenie a or bnajpierw przed wrzuceniem go do kiedy. Bardziej zaskakujące i trudniejsze w obsłudze jest to, że język ma tokeny, które zmieniają zachowanie w zależności od kontekstu, a wtedy nie byłoby możliwe użycie prawdziwego orwyrażenia po prawej stronie kiedy.
Taywee,
99

Możesz skorzystać z „ikony” Ruby lub składni spłaszczania.

To sprawia, że ​​przerośnięte whenklauzule - masz około 10 wartości do przetestowania na gałąź, jeśli dobrze rozumiem - są trochę bardziej czytelne. Ponadto można zmodyfikować wartości do testowania w czasie wykonywania. Na przykład:

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

Innym powszechnym podejściem byłoby użycie skrótu jako tabeli wysyłania, z kluczami dla każdej wartości cari wartościami, które są niektórymi obiektami wywołującymi kodowanie kodu, który chcesz wykonać.

pilcrow
źródło
Skończyło się na tym, chociaż źle się czuję, zabierając komuś znak wyboru: D
Nick
Doskonałe rozwiązanie dla długich whenlinii. Dzięki za udostępnienie.
Pistos 20.04.16
0

Innym dobrym sposobem na umieszczenie logiki w danych jest coś takiego:

# 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
Hew Wolff
źródło
Nie chcę być niegrzeczny, ale przegłosowałem, ponieważ jest to mniej wydajne zarówno w czasie, jak i przestrzeni. Jest także bardziej złożony i mniej czytelny niż dwie pozostałe odpowiedzi. Jaka byłaby korzyść ze stosowania tej metody?
Nick
Umieszcza całą klasyfikację w jednym obiekcie. Możesz teraz robić różne rzeczy z tym obiektem, na przykład serializować go i wysyłać do kogoś innego, aby wyjaśnić swoją logikę lub przechowywać go w bazie danych i pozwolić innym na edycję. (Logika zmieni się wkrótce, gdy pojawią się nowe modele samochodów, prawda?) Możesz spojrzeć na „sterowane przez stół”.
Hew Wolff
YAGNI („Nie będziesz go potrzebować”) może ubiegać się tutaj. Projekt poświęca wydajność czasu / przestrzeni i czytelność dla scenariusza, który może istnieć w przyszłości, ale jeszcze nie istnieje. Koszt jest teraz zapłacony, ale nagroda może nigdy nie zostać zebrana.
Nick