Понимание "||" OR в операторах If в Ruby
Вкратце, почему следующие три строки не идентичны в их воздействии?
if @controller.controller_name == "projects" || @controller.controller_name == "parts"
if @controller.controller_name == ("projects" || "parts")
if @controller.controller_name == "projects" || "parts"
Первый дает мне результат, который я хочу, но поскольку на самом деле больше вариантов, чем просто проектов и частей, использование этой формы создает подробное утверждение. Другие два более компактны, но не дают мне того же результата.
Ответы
Ответ 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]