Оператор Case с несколькими значениями в каждом блоке «когда»

315

Лучший способ описать то, что я ищу, это показать вам неудачный код, который я пробовал до сих пор:

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
Эта ссылка содержит более качественную сводку инструкций case в Ruby (а также примеры синтаксиса regexp и splat).
rsenna
Я не знаю почему, но эта странная ситуация происходит: Когда я пишу это: when "toyota", "lexus"я получаю: unexpected tSTRING_BEG, expecting keyword_do or '{' or '(' (SyntaxError). Однако когда я пишу это when "toyota","lexus", это работает. Единственная разница - это пробел после запятой.
Фуркан Айхан
@FurkanAyhan Это странно. Я пошел дальше и протестировал код, чтобы убедиться, что он работает. Я предполагаю, что в вашем коде происходит что-то еще, что делает его ошибочным. Возможно ли, что вы забыли закрыть строку или что-то в этом роде?
Чарльз Колдуэлл
1
ну, это работает, но, поскольку ruby ​​фокусируется на простоте программиста, мне интересно, почему он не поддерживает стандарт || или или'? Это немного сбивает с толку
Зия Уль Рехман
2
Ruby не поддерживает orили ||здесь, потому что whenсправа от него находится последовательность разделенных запятыми выражений, а не один идентификатор. Из-за этого, если у вас есть when a or b, не ясно, следует ли это принимать в качестве эквивалента when a, bили when (a or b), последнее из которых a or bсначала вычисляет выражение, прежде чем выбросить его в when. Более удивительным и менее простым в обращении с языком является наличие токенов, которые изменяют поведение в зависимости от контекста, и тогда вы не сможете использовать настоящее orвыражение в правой части слова «когда».
Тайвэ
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
Хью Вольф
источник
Я не хочу быть грубым, но я подавлен, потому что это менее эффективно и во времени и в пространстве. Это также более сложный и менее читаемый, чем два других ответа. Какая польза от использования этого метода?
Ник
Это помещает всю вашу классификацию в один объект. Теперь вы можете что-то делать с этим объектом, например, сериализовать его и отправить кому-то еще, чтобы объяснить вашу логику, или сохранить его в базе данных и позволить людям редактировать его. (Логика изменится довольно скоро, когда появятся новые модели автомобилей, не так ли?) Вы можете посмотреть на «управляемый столом».
Хью Вольф
ЯГНИ («Тебе это не понадобится») может подать заявку здесь. Дизайн жертвует эффективностью времени и пространства и удобочитаемостью для сценария, который может существовать в будущем, но еще не существует. Стоимость уже оплачена, но вознаграждение может никогда не быть получено.
Ник