理解Ruby中的if条件中的“||”OR运算符

简而言之,为什么以下三条线的影响不一样?

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

第一个给出了我想要的结果,但实际上有更多选项而不仅仅是项目和部分,使用该表单创建了一个详细的语句。 另外两个更紧凑,但不给我相同的结果。

||的确切语义 是:

  • 如果第一个表达式不是nil或false,则返回它
  • 如果第一个表达式为nil或false,则返回第二个表达式

所以你的第一个表达式是,如果@controller.controller_name == "projects" ,则表达式短路并返回true 。 如果没有,它会检查第二个表达式。 第二个和第三个变体基本上if @controller.controller_name == "projects" ,因为"projects" || "parts" "projects" || "parts"等于"projects" 。 你可以在irb中尝试这个:

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

你想做的是

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

不同之处在于发生的事情的顺序。 还有|| 没有做你认为它在2和3中做的事情。

你也可以这样做

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

如果您需要添加更多匹配项,请在将来减少代码。

|| 也是一个空的合并运算符,所以

 "projects" || "parts" 

将返回第一个非null的字符串(在本例中为“projects”),这意味着在后两个示例中,您将始终在评估:

 if @controller.controller_name == "projects" 

解雇irb,您可以检查是否发生了这种情况:

 a = "projects" b = "parts" a || b 

返回projects

基本上,==不会分配给其他运营商。 3 * (2+1)3 * 2 + 3 * 1相同的原因是乘法在加法上分布。

||的值 表达式将是其论据之一。 因此第二个陈述相当于:

 if @controller.controller_name == "projects" 

|| 优先级低于==,因此第3个语句相当于:

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

那里有几件不同的事情:

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

这给出了我想要的行为。 逻辑非常基本:如果控制器名称是“projects”或“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" 

这个甚至更加狡猾。 这总是会导致真实的。 它将首先检查控制器名称是否等于“projects”。 如果是,则语句​​的计算结果为true。 如果没有,它会自行评估“部分”:在ruby中也会评估为“true”(出于布尔逻辑的目的,任何非零对象都被视为“true”)

获得非详细解决方案的简单方法是

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

这实际上与||无关 而是在ruby中被认为是真实的价值。 一切都是假的,零是真的。

逻辑或运算符|| 适用于布尔表达式,因此在字符串上使用它不会做你想要的。

有几种方法可以实现您想要的更简洁,更易读的内容。

使用Array #include? 和一个简单的if语句:

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

使用案例陈述:

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

第一个将“projects”和“parts”字符串文字与@controller.controller_name变量进行比较。

第二个评估(“projects”||“parts”),这是“项目”,因为“projects”字符串文字既不是false也不是nil或空字符串,并将它与@controller.controller_name进行比较

第三个比较@controller.controller_name和“projects”,如果它们相等,则返回true ,如果不是,则返回“parts”,对于if语句,返回等于true