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


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.