如何在Ruby中编写switch语句?

Ruby使用case表达式代替。

case x
when 1..5
  "It's between 1 and 5"
when 6
  "It's 6"
when "foo", "bar"
  "It's either foo or bar"
when String
  "You passed a string"
else
  "You gave me #{x} -- I have no idea what to do with that."
end

通过使用===运算符将when-clause中的对象与case-clause中的对象进行比较来完成比较。也就是说,它是,1..5 === xString === x不是x === 1..5。这允许您在上面看到复杂的语义,您可以在其中使用范围和类以及各种各样的东西,而不仅仅是测试相等性。

switch许多其他语言中的语句不同,Ruby的case不存在转场,因此不需要when用a 来结束每个语句break。此外,您可以为单个when喜欢指定多个匹配项when "foo", "bar"

答案


case...when在处理类时表现得有点意外。这是由于它使用===操作员。

该操作符按照预期的方式工作,但不包含类:

1 === 1           # => true
Fixnum === Fixnum # => false

这意味着如果你想对case ... when对象的类进行操作,这将不起作用:

obj = 'hello'
case obj.class
when String
  print('It is a string')
when Fixnum
  print('It is a number')
else
  print('It is not a string')
end

将打印“它不是一个字符串”。

幸运的是,这很容易解决。该===运算符已被定义,以便true在与类一起使用时返回,并将该类的实例作为第二个操作数提供:

Fixnum === 1 # => true

简而言之,上面的代码可以通过删除.class

obj = 'hello'
case obj  # was case obj.class
when String
  print('It is a string')
when Fixnum
  print('It is a number')
else
  print('It is not a string')
end

我今天遇到这个问题的同时寻找答案,这是第一个出现的页面,所以我认为这对其他人在同一情况下会有用。


这是通过Ruby中的情况完成的。另请参阅维基百科上的这篇文章

引:

case n
when 0
  puts 'You typed zero'
when 1, 9
  puts 'n is a perfect square'
when 2
  puts 'n is a prime number'
  puts 'n is an even number'
when 3, 5, 7
  puts 'n is a prime number'
when 4, 6, 8
  puts 'n is an even number'
else
  puts 'Only single-digit numbers are allowed'
end

另一个例子:

score = 70

result = case score
   when 0..40 then "Fail"
   when 41..60 then "Pass"
   when 61..70 then "Pass with Merit"
   when 71..100 then "Pass with Distinction"
   else "Invalid Score"
end

puts result

Ruby Programming Programming Lanugage(第1版,O’Reilly)的第123页(我正在使用Kindle)中,它表示thenwhen子句后面的关键字可以用换行符或分号代替(就像在if then else语法中一样)。(Ruby 1.8也允许冒号代替then…但是这个语法在Ruby 1.9中不再允许。)


情况……当

为了给查克的答案增加更多的例子:

带参数:

case a
when 1
  puts "Single value"
when 2, 3
  puts "One of comma-separated values"
when 4..6
  puts "One of 4, 5, 6"
when 7...9
  puts "One of 7, 8, but not 9"
else
  puts "Any other thing"
end

没有参数:

case
when b < 3
  puts "Little than 3"
when b == 3
  puts "Equal to 3"
when (1..10) === b
  puts "Something in closed range of [1..10]"
end

请注意kikito警告的问题


在Ruby 2.0中,您还可以在case语句中使用lambdas ,如下所示:

is_even = ->(x) { x % 2 == 0 }

case number
when 0 then puts 'zero'
when is_even then puts 'even'
else puts 'odd'
end

您还可以使用带有自定义的Struct轻松创建自己的比较器 ===

Moddable = Struct.new(:n) do
  def ===(numeric)
    numeric % n == 0
  end
end

mod4 = Moddable.new(4)
mod3 = Moddable.new(3)

case number
when mod4 then puts 'multiple of 4'
when mod3 then puts 'multiple of 3'
end

(例子取自“ 可以与Ruby 2.0中的case语句一起使用吗? ”)。

或者,完整的课程:

class Vehicle
  def ===(another_vehicle)
    self.number_of_wheels == another_vehicle.number_of_wheels
  end
end

four_wheeler = Vehicle.new 4
two_wheeler = Vehicle.new 2

case vehicle
when two_wheeler
  puts 'two wheeler'
when four_wheeler
  puts 'four wheeler'
end

(来自“ Ruby案例声明的工作原理和你能做什么 ”的例子。)


许多编程语言,尤其是那些源自C语言的编程语言,都支持所谓的“ 切换延迟”。我正在寻找在Ruby中执行相同操作的最佳方法,并认为它可能对其他人有用:

在类似C语言的语言中,穿透通常看起来像这样:

switch (expression) {
    case 'a':
    case 'b':
    case 'c':
        // Do something for a, b or c
        break;
    case 'd':
    case 'e':
        // Do something else for d or e
        break;
}

在Ruby中,可以通过以下方式实现相同的功能:

case expression
when 'a', 'b', 'c'
  # Do something for a, b or c
when 'd', 'e'
  # Do something else for d or e
end

这不是完全等价的,因为在'a'执行'b'或之前不可能执行一段代码'c',但在大多数情况下,我发现它的相似程度足以以相同的方式有用。


您可以使用正则表达式,例如查找字符串类型:

case foo
when /^(true|false)$/
   puts "Given string is boolean"
when /^[0-9]+$/ 
   puts "Given string is integer"
when /^[0-9\.]+$/
   puts "Given string is float"
else
   puts "Given string is probably string"
end

Ruby的case将使用相等的操作数===(谢谢@JimDeville)。更多信息可在“ Ruby运营商 ”处获得。这也可以使用@mmdemirbas示例(不带参数)完成,只有这种方法对于这些类型的案例来说更清晰。

添加评论

友情链接:蝴蝶教程