ZetCode

Ruby 的 when 和 case 关键字

最后修改日期:2025 年 4 月 27 日

本教程将介绍 Ruby 中 casewhen 关键字的用法。它们提供了类似于 switch 语句的强大条件逻辑。

case 关键字启动一个条件块,该块将一个值与多个可能性进行比较。when 关键字定义了 case 语句中的每个比较分支。

Ruby 的 case/when 比传统的 switch 语句更灵活。它使用 === 运算符进行比较,允许使用范围、类和正则表达式。

基本的 case/when 示例

这个简单的例子演示了 case 语句的基本结构。它将一个数字与几个可能的值进行匹配。

basic_case.rb
grade = 85

case grade
when 90..100
  puts "A"
when 80..89
  puts "B"
when 70..79
  puts "C"
else
  puts "F"
end

代码检查分数属于哪个范围,并打印相应的字母。else 子句处理未被 when 条件匹配的任何值。

带多个 when 条件的 case

单个 when 子句可以通过用逗号分隔多个值来匹配。这使得代码对于等效结果更加简洁。

multiple_when.rb
day = "Tuesday"

case day
when "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"
  puts "Weekday"
when "Saturday", "Sunday"
  puts "Weekend"
else
  puts "Invalid day"
end

这会将所有工作日和周末分组在一起。逗号在条件之间充当 OR 运算符。else 处理意外的输入。

没有显式值的 case

Ruby 允许没有显式值的 case 语句进行比较。在这种形式中,每个 when 条件都评估为布尔表达式。

no_value_case.rb
x = 15
y = 20

case
when x > y
  puts "x is greater than y"
when x < y
  puts "x is less than y"
else
  puts "x equals y"
end

这种风格类似于一系列 if/elsif 条件。每个 when 表达式都必须评估为 true 或 false。第一个为 true 的条件将执行其块。

带类匹配的 case

Ruby 的 case 使用 ===,允许与类进行匹配。此示例演示了 case/when 的类型检查。

class_matching.rb
value = [1, 2, 3]

case value
when String
  puts "It's a string"
when Numeric
  puts "It's a number"
when Array
  puts "It's an array"
else
  puts "Unknown type"
end

=== 运算符检查值是否是每个类的实例。与多个 is_a? 调用相比,这提供了干净的类型检查语法。

带正则表达式的 case

=== 运算符也适用于正则表达式,使 case/when 成为字符串模式匹配的理想选择。

regex_case.rb
email = "user@example.com"

case email
when /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z]+)*\.[a-z]+\z/i
  puts "Valid email"
when /@/
  puts "Contains @ but invalid format"
else
  puts "Not an email address"
end

第一个 when 检查有效的电子邮件模式。第二个匹配包含 @ 但格式无效的字符串。else 处理所有其他情况。

带 Proc 和 Lambda 的 case

由于 === 可以调用 proc,我们可以在 when 条件中使用它们来进行自定义匹配逻辑。

proc_case.rb
is_positive = ->(n) { n > 0 }
is_negative = ->(n) { n < 0 }

number = -5

case number
when is_positive
  puts "Positive number"
when is_negative
  puts "Negative number"
else
  puts "Zero"
end

每个 lambda 都将 case 值作为参数进行调用。第一个匹配的条件将执行其块。这允许进行复杂的自定义匹配逻辑。

在方法分派中使用 case

此示例展示了如何根据输入类型使用 case/when 进行方法分派,类似于函数式语言中的模式匹配。

method_dispatch.rb
def process(input)
  case input
  when Hash
    input.transform_values(&:to_s)
  when Array
    input.map(&:to_s)
  when String
    input.upcase
  else
    input.to_s
  end
end

puts process({a: 1, b: 2})   # {"a"=>"1", "b"=>"2"}
puts process([1, 2, 3])      # ["1", "2", "3"]
puts process("hello")        # "HELLO"
puts process(42)             # "42"

process 方法使用 case/when 适当处理不同的输入类型。这种模式在 Ruby 中很常见,用于编写接受多种类型的灵活方法。

来源

Ruby 控制表达式文档

本教程通过示例介绍了 Ruby 的 case 和 when 语句,展示了值匹配、类型检查、正则表达式模式和自定义匹配逻辑。

作者

我叫 Jan Bodnar,是一名充满激情的程序员,拥有丰富的编程经验。我从 2007 年开始撰写编程文章。迄今为止,我已撰写了 1400 多篇文章和 8 本电子书。我在编程教学方面有十多年的经验。

列出 所有 Ruby 教程