Ruby 案例陈述:多个变量,每个变量具有多个可能性

Ruby 案例陈述:多个变量,每个变量具有多个可能性,ruby,Ruby,起初我认为这种语法是有效的,但当只检查组的第一个值时,如果第一个值中的任何一个失败,它将返回locked。坏消息是或操作数在此不起作用 def lock(a,b,c,d) case [a,b,c,d] when[(3||5||7), 2, (5||6), (8||9||0)] "unlocked" else "locked" end end lock(3, 2, 5, 8) lock(5, 2, 5, 0) lock(5, 2, 6, 8) lo

起初我认为这种语法是有效的,但当只检查组的第一个值时,如果第一个值中的任何一个失败,它将返回locked。坏消息是
操作数在此不起作用

def lock(a,b,c,d)
  case [a,b,c,d]
    when[(3||5||7), 2, (5||6), (8||9||0)]
      "unlocked"
    else
      "locked"
  end
end

lock(3, 2, 5, 8)
lock(5, 2, 5, 0)
lock(5, 2, 6, 8)
lock(7, 2, 5, 8)
lock(7, 2, 6, 9)

我可以为每个变量执行if-else语句,但我希望有一种方法可以执行case语句,而不必执行多个when语句。

我将选择循环数组,而不是使用
case
语句,如下所示:

def lock(a,b,c,d)
  combination = [[3,5,7], [2], [5,6], [8,9,0]]
  attempt     = [a,b,c,d]

  combination.each_with_index do |position, i|
    return "locked" unless position.include?(attempt[i])
  end

  "unlocked"
end
产出:

lock(3, 2, 5, 8)
#=> "unlocked"

lock(5, 2, 5, 0)
#=> "unlocked"

lock(5, 2, 6, 8)
#=> "unlocked"

lock(7, 2, 5, 8)
#=> "unlocked"

lock(7, 2, 6, 9)
#=> "unlocked"

lock(1, 2, 3, 4)
#=> "locked"

为什么你的解决方案失败了

正如在他的著作中指出的那样,当与[(3 | 5 | 7),2,(5 | 6),(8 | 9 | 0)]结合时,
的计算结果是
[3,2,5,8]
。这是因为括号中的每个表达式都是先求值的,因此,将其分解为:

(3 || 5 || 7)
#=> 3

2
#=> 2

(5 || 6)
#=> 5

(8 || 9 || 0)
#=> 8
这是因为
|
正在计算值是否真实,即既不是
nil
也不是
false
。一旦表达式得到真实值,它将返回该值,不再进一步查看。因此,任何数字都将计算为truthy,因此,您将始终得到每个表达式的第一个数字

回到您的
案例
语句,它与像这样编写它是完全一样的:

case [a,b,c,d]
when [3, 2, 5, 8]
  "unlocked"
else
  "locked"
end

现在请考虑< <代码>案例> /COD>语句将评估< <代码>案例> />代码中的对象是否与<<代码>中的< < /> >相同。因此,在中,您的案例将类似于:

[a,b,c,d] === [3, 2, 5, 8]
只有在您调用
lock(3,2,5,8)
时,才会返回
true
(和
“unlocked”

也可以考虑在时使用多个值,使用<代码>,这样使用类似的东西将起作用:

case [a,b,c,d]
when [3, 2, 5, 8], [5, 2, 5, 0] then "unlocked"
else "locked"
end
其中
when
相当于执行以下操作:

[a,b,c,d] === [3, 2, 5, 8] || [5, 2, 5, 0]

正如其他人所解释的,这个问题本身不适合使用案例陈述

因为变量看起来是数字,所以可以将它们转换为字符串并使用正则表达式

def lock(entry, valid)
  r = /#{valid.map { |a| '['+a.join('|')+']' }.join }/
  entry.join.match?(r) ? 'unlocked' : 'locked'  
end
假设

valid = [[3, 5, 7], [2], [5, 6], [8, 9, 0]]
我们为
valid
的值计算以下正则表达式:

r #=> /[3|5|7][2][5|6][8|9|0]/
试试看:

lock([3, 2, 5, 8], valid) #=> "unlocked"
lock([5, 2, 5, 0], valid) #=> "unlocked"
lock([5, 2, 6, 8], valid  #=> "unlocked"
lock([7, 2, 5, 8], valid) #=> "unlocked"
lock([7, 2, 6, 9], valid) #=> "unlocked"
lock([5, 2, 4, 0], valid) #=> "locked"

我认为你误解了案例陈述的工作原理;它们使用相等运算符将case子句中的对象(在您的示例中,
[a,b,c,d]
)与每个when子句中的对象进行比较。请注意,when子句中的对象只是一个数组,它将计算为
[3,2,5,8]
,你的评论为我澄清了一切。当
的功能类似于if-else语句时,我认为是
。所以你的意思是,当对象
时,它实际上只是在做
case对象
==
?如果是这样的话,
|
不会抛出某种语法错误,这很有趣。我想这就是为什么我认为这是可能的。or运算符不会抛出语法错误,因为这是完全有效的语法
3 | | 5
的计算结果仅为
3
。真聪明!谢谢,我会考虑的。我只是想更多地理解
case
语句,因为我从来没有使用过它们。我只是在写同样的语句,我认为这是最好的答案。@WolfgangTruong检查更新的答案,我希望它有助于更好地理解。