Ruby:为什么这个WHEN陈述式不适用于两个条件?

时间:2018-11-05 11:51:40

标签: ruby conditional operators

我的Ruby代码中有一个case,它基本上试图以几种方式匹配字符串,并相应地对字符串做不同的事情,就像这样:

case inst
when Rx_inst1
  (some function)
when Rx_inst2
  (some other function)
end

这很漂亮(我没有发布RegEx,因为它非常非常长而且运行良好)。但是,当我尝试实现以下修改时,即使RegEx匹配字符串,如果条件包含子字符串,该条件也不会执行:

case inst
when Rx_inst1
  (some function)
when Rx_inst2 && !/dom\./
  (some other function)
end

Rx_inst2等于inst或之前匹配的任何其他类型的字符串时,它停止匹配Nm. Friese = Fryzyjczyk, koń fryzyjski

我用&& /dom\./&& inst.include?('dom.')得到了完全相同的结果,根据其他答案,这是正确的语法。我在做什么错了?

4 个答案:

答案 0 :(得分:2)

case inst
when Rx_inst1
  (some function)
when Rx_inst2 && !/dom\./
  (some other function)
end

case用。===运算符转换为一堆if / elsif / else语句 因此您的代码等同于

if Rx_inst1 === inst
  (some function)
elsif (Rx_inst2 && !/dom\./) === inst
  (some other function)
end

(Rx_inst2 && !/dom\./) === inst的工作方式如下:

  1. (Rx_inst2 && !/dom\./)部分的计算结果为!/dom\./(Rx_inst2是RegEx,并且不是nil或false)
  2. !/dom\./ === inst为您提供结果

所以 只要when Rx_inst2 && !/dom\./匹配,!/dom\./ === inst就会匹配

答案 1 :(得分:1)

很明显,Rx_inst2 && !/dom\./返回(由于短路评估)第二个操作数的值,!/dom\/(假设Rx_inst2确实是Regexp,因此真实)。您可能需要在Rx_inst2中修改此正则表达式,没有简短的答案。

或者,您可以对所有case表达式进行一些更改,如下所示:

case
when inst =~ Rx_inst1
  # (some function)
when inst =~ Rx_inst2 && !(inst =~ /dom\./)
  # (some other function)
end

但我认为这不是特别优雅的形式。

答案 2 :(得分:1)

@Darigazz很好地解释了case的工作原理以及代码错误的原因。您可以通过以下几种方式编写案例声明。

#1

case inst
when Rx_inst1
  m1  
when Rx_inst2
  m2 if inst.match? /dom\./
end
如果nil中的inst.match? /dom\./ #=> false,则返回

m2 if inst.match? /dom\./。根据要求,if可能会替换为unless

#2

case inst
when Rx_inst1
  m1  
when /(?=.*dom\.)#{Rx_inst2}/
  m2
end

其中(?=.*dom\.)正向超前。例如,

Rx_inst2 = /Bubba|Trixie/
/(?=.*dom\.)#{Rx_inst2}/
   #=> /(?=.*dom\.)(?-mix:Bubba|Trixie)/

根据要求,(?=.*dom\.)可能会被负向超前 (?!.*dom\.)取代。

答案 3 :(得分:0)

好的,事实证明我是这样工作的:

when (!inst.include?('dom.') and Rx_inst2)

尽管如此,我仍然不明白为什么我必须做以下三件事:

  1. 更改操作顺序
  2. 将整个表达式括起来
  3. 显式地调用第一个,然后隐式地调用第二个