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?

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


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ć.


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

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
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.