Оператор 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

Я не хочу быть грубым, но я подавлен, потому что это менее эффективно и во времени и в пространстве. Это также более сложный и менее читаемый, чем два других ответа. Какая польза от использования этого метода?
— Ник

Это помещает всю вашу классификацию в один объект. Теперь вы можете что-то делать с этим объектом, например, сериализовать его и отправить кому-то еще, чтобы объяснить вашу логику, или сохранить его в базе данных и позволить людям редактировать его. (Логика изменится довольно скоро, когда появятся новые модели автомобилей, не так ли?) Вы можете посмотреть на «управляемый столом».
— Хью Вольф

ЯГНИ («Тебе это не понадобится») может подать заявку здесь. Дизайн жертвует эффективностью времени и пространства и удобочитаемостью для сценария, который может существовать в будущем, но еще не существует. Стоимость уже оплачена, но вознаграждение может никогда не быть получено.
— Ник
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.