Виписка з декількома значеннями в кожному блоці "коли"


314

Найкращий спосіб описати те, що я шукаю - показати вам невдалий код, який я намагався до цього часу:

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

У мене приблизно 4 або 5 різних whenситуацій, які повинні бути спровоковані приблизно 50 різними можливими значеннями car. Чи є спосіб зробити це за допомогою caseблоків чи слід спробувати масивний ifблок?

Відповіді:


669

У caseзаяві, a ,- еквівалент ||у ifтвердженні.

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

Деякі інші речі, які ви можете зробити із заявою справи Ruby


1
Це посилання має кращий підсумок тверджень про випадки у Ruby (і воно включає приклади синтаксису regexp та splat).
rsenna

Я не знаю чому, але ця дивна ситуація відбувається: Коли я пишу це: when "toyota", "lexus"я отримую: unexpected tSTRING_BEG, expecting keyword_do or '{' or '(' (SyntaxError). Однак, коли я пишу так: when "toyota","lexus"це працює. Єдина відмінність - пробіл після коми.
Фуркан Айхан

@FurkanAyhan Це дивно. Я пішов і перевірив код лише для того, щоб переконатися, що він працює. Я здогадуюсь, що у вашому коді відбувається щось інше, що робить помилку такою. Чи можливо ви забули десь закрити рядок чи щось подібне?
Чарльз Колдвелл

1
добре, це працює, але оскільки рубінова зосереджена на простоті програміста, мені цікаво, чому він не підтримує стандарт || або "чи"? Це щось заплутано
Зія Уль Рехман Магхал

2
Ruby не підтримує orабо ||тут, тому що whenбере ряд виразів, розділених комами, праворуч від нього, а не одного ідентифікатора. Через це, якщо б у вас було when a or b, не ясно, чи слід це вважати еквівалентом when a, bабо when (a or b), останній з яких оцінює вираз a or bспочатку перед тим, як кинути його в коли. Більш дивно і менш просто керувати мовою, щоб мати лексеми, які змінюють поведінку залежно від контексту, і тоді ви не зможете використовувати справжній orвираз праворуч від часу.
Taywee

99

Ви можете скористатися синтаксисом рубіну або сплеском синтаксису.

Це робить перерослі whenпропозиції - у вас є близько 10 значень для тестування на кожну галузь, якщо я правильно розумію - на мою думку, трохи читабельніші. Крім того, ви можете змінювати значення для тестування під час виконання. Наприклад:

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

Іншим поширеним підходом було б використання хешу в якості таблиці відправлення, з ключами для кожного значення carта значень, які є об'єктом, що викликається, інкапсулюючи код, який потрібно виконати.


Це те, що я в кінцевому підсумку використав, хоча мені погано знімають чиїсь галочки: D
Нік

Блискуче рішення для довгих whenліній. Дякую, що поділились.
Пістос

0

Ще один приємний спосіб ввести свою логіку в дані:

# 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

Я не маю на увазі бути грубим, але я вважаю, що це менш ефективно як у часі, так і в просторі. Він також складніший і менш читабельний, ніж два інших відповіді. Яка була б користь від використання цього методу?
Нік

Це вміщує всю вашу класифікацію в один об'єкт. Тепер ви можете робити речі з цим об’єктом, наприклад, серіалізувати його та надсилати комусь іншому, щоб пояснити вашу логіку, або зберегти в базі даних та дозволити людям редагувати її. (Логіка зміниться досить скоро, коли вийдуть нові моделі автомобілів, правда?) Ви можете виглядати "керованими на столі".
Wolff

YAGNI ("Вам це не потрібно") може застосовуватися тут. Дизайн жертвує ефективністю часу та простору та читабельністю для сценарію, який може існувати у майбутньому, але ще не існує. Вартість виплачується зараз, але винагорода ніколи не буде отримана.
Нік
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.