带有多个变量的Ruby case语句

时间:2011-02-01 03:16:00

标签: ruby pattern-matching case

Ruby需要一个相当强大的case..when..else构造,以便在需要将条件与单个变量匹配时。在不简单地嵌套case语句的情况下,将标准与多个变量匹配的“规范”方法是什么?

在数组中包装多个变量(如[x, y])并与之匹配并不等效,因为Ruby不会将神奇的case ===运算符应用于元素阵列;运算符仅适用于数组本身。

我将继续前进并回答一个社区维基的回答,并在这个问题上被击败。

4 个答案:

答案 0 :(得分:4)

您需要使用if..elsif..else,并确保要匹配的变量显示在===运算符的右侧(case基本上是x )。

例如,如果您想根据某些条件匹配yif (SomeType === x) && (1..10 === y) some_value elsif (:some_symbol === x) && (11..20 === y) some_other_value end

{{1}}

答案 1 :(得分:3)

这是添加===的简单方法:

class Array
  def ===(other)
    return false if (other.size != self.size)

    other_dup = other.dup
    all? do |e|
      e === other_dup.shift
    end
  end
end

[
  ['foo', 3],
  %w[ foo bar ],
  %w[ one ],
  []
].each do |ary|

  ary_type = case ary
  when [String, Fixnum] then "[String, Fixnum]"
  when [String, String] then "[String, String]"
  when [String] then "[String]"
  else
    "no match"
  end

  puts ary_type

end

# >> [String, Fixnum]
# >> [String, String]
# >> [String]
# >> no match

答案 2 :(得分:3)

由于Ruby的when关键字支持以逗号分隔的值列表,因此您可以使用splat *运算符。当然,这是假设您指的是一组离散值,或者可能成为一个数组。

splat运算符将参数列表转换为数组,如

中常见的那样
def method_missing(method, *args, &block)

鲜为人知的是,它还执行逆操作 - 将数组转换为参数列表。

所以在这种情况下,你可以做类似

的事情
passing_grades = ['b','c']
case grade
when 'a'
  puts 'great job!'
when *passing_grades
  puts 'you passed'
else
  puts 'you failed'
end

答案 3 :(得分:2)

如果这种模式在您的代码中足够常见以保证经济表达,您可以自己完成:

class BiPartite
  attr_reader :x, :y

  def self.[](x, y)
    BiPartite.new(x, y)
  end

  def initialize(x, y)
    @x, @y = x, y
  end

  def ===(other)
    x === other.x && y === other.y
  end
end

....

case BiPartite[x, y]
when BiPartite[SomeType, 1..10]
  puts "some_value"
when BiPartite[:some_symbol, 11..20]
  puts "some_other_value"
end