Подтвердить что ты не робот

Понимание "||" OR в операторах If в Ruby

Вкратце, почему следующие три строки не идентичны в их воздействии?

if @controller.controller_name == "projects" || @controller.controller_name == "parts"

if @controller.controller_name == ("projects" || "parts")

if @controller.controller_name == "projects" || "parts"

Первый дает мне результат, который я хочу, но поскольку на самом деле больше вариантов, чем просто проектов и частей, использование этой формы создает подробное утверждение. Другие два более компактны, но не дают мне того же результата.

4b9b3361

Ответ 1

точная семантика || являются:

  • Если первое выражение не равно nil или false, верните его
  • Если первое выражение равно nil или false, верните второе выражение

так что ваше первое выражение работает, если @controller.controller_name == "projects", то выражение short-circuit и возвращает true. если нет, он проверяет второе выражение. второй и третий варианты по существу if @controller.controller_name == "projects", так как "projects" || "parts" равно "projects". вы можете попробовать это в irb:

>> "projects" || "parts"
=> "projects"

что вы хотите сделать, это

if ["projects", "parts"].include? @controller.controller_name

Ответ 2

Разница - это порядок того, что происходит. Также || не делает то, что, по вашему мнению, делает в 2 и 3.

Вы также можете сделать

if ['projects','parts'].include?(@controller.controller_name)

чтобы уменьшить код в будущем, если вам нужно добавить больше совпадений.

Ответ 3

|| также является нулевым коалесцирующим оператором, поэтому

"projects" || "parts"

вернет первую строку, которая не является нулевой (в данном случае "проекты" ), что означает, что во вторых двух примерах вы всегда будете оценивать:

if @controller.controller_name == "projects"

Запуская irb, вы можете проверить, что это происходит:

a = "projects"
b = "parts"

a || b

возвращает projects

Ответ 4

Там происходит несколько разных вещей:

if @controller.controller_name == "projects" || @controller.controller_name == "parts"

это дает поведение, которое вы хотите, я предполагаю. Логика довольно простая: верните true, если имя элемента управления является либо "проектами", либо "частями"

Другой способ сделать это:

if ["projects", "parts", "something else..."].include? @controller.controller_name

Это проверит, находится ли имя контроллера где-то в списке.

Теперь для других примеров:

if @controller.controller_name == ("projects" || "parts")

Это не будет делать то, что вы хотите. Сначала он будет оценивать ("projects" || "parts") (что приведет к "проектам" ), и тогда будет проверяться только, совпадает ли имя контроллера с этим.

if @controller.controller_name == "projects" || "parts"

Это становится еще более странным. Это всегда приведет к истине. Сначала проверьте, совпадает ли имя контроллера с "проектами". Если это так, оператор оценивает значение true. Если нет, он оценивает "части" на своем собственном: который также оценивает "true" в ruby ​​(любой объект non nil считается "истинным" для логической логики ")

Ответ 5

В принципе, == не распространяется по другим операторам. Причина 3 * (2+1) такая же, как 3 * 2 + 3 * 1 заключается в том, что умножение распределяется по сложениям.

Значение a || выражение будет одним из его аргументов. Таким образом, второй оператор эквивалентен:

if @controller.controller_name == "projects"

|| имеет более низкий приоритет, чем ==, поэтому третий оператор эквивалентен:

if (@controller.controller_name == "projects") || "ports"

Ответ 6

Простым способом получить неопределенное решение является

if ["a", "b", "c"].include? x

Это фактически не имеет ничего общего с ||, а скорее, какие значения считаются истинными в ruby. Все, что нужно сохранить false, равно нулю.

Ответ 7

Логический или оператор || работает над булевыми выражениями, поэтому используя он на строках не делает то, что вы хотите.

Существует несколько способов добиться того, что вы хотите, чтобы быть более подробным и более удобочитаемым.

Использование массива # include? и простой оператор if:

if ["projects", "parts"].include? @controller.controller_name
  do_something
else
  do_something_else
end

Использование case-statement:

case @controller.controller_name
when "projects", "parts" then
  do_something
else
  do_something_else
end

Ответ 8

Сначала сравниваются строковые литералы "проекты" и "части" с переменной @controller.controller_name.

Второе оценивает ( "проекты" "части" ), которые являются "проектами", потому что "проекты" строковый литерал ни false, либо nil, либо пустая строка и сравнивают ее с @controller.controller_name

Третий сравнивает @controller.controller_name и "projects", и если они равны, он возвращает true, если они не возвращают "части" , которые равны true для оператора if.

Ответ 9

Я вижу много людей, предпочитающих include? сравнение.

Я предпочитаю использовать .in? оператор. Это намного более кратко. А также более читабельным, поскольку мы не задаем вопросы массиву, мы задаем вопросы к переменной, которую вы хотите задать: в вашем случае - имя контроллера.

@controller.controller_name.in? ["projects", "parts"]

Или даже лучше

@controller.controller_name.in? %w[projects parts]