Ruby:Case语句中的两个条件

时间:2019-11-10 13:39:17

标签: ruby-on-rails ruby ruby-on-rails-5

如何使用case语句并检查两个条件?

我需要检查一个项目是否为数组,并且仅包含字符串类。

a = ['one','twon']  # => ["one", "twon"]

case a                                                                         # => 
when String
  puts "string
when Array && a.all?{|obj| obj.is_a?(String) }
   puts 'an array with only string classes'
else
  raise ArgumentError, "unsupported object #{obj}:#{obj.class}"
end

上面的代码在返回“仅包含字符串类的数组”语句时返回else情况

2 个答案:

答案 0 :(得分:4)

case语句中的条件不是布尔表达式;它们是使用===运算符与目标对象进行比较的值。当然,任何类都可以重写该运算符,但是预定义的运算符仅在少数条件下返回true(例如is_a?中包含等于=~等)。当布尔表达式作为when条件时,如果该表达式为true,则不会触发匹配。当目标对象===的值是表达式时,它将触发匹配,对于大多数对象,obj === true本身不是真的。

因此,在这种情况下,您可能希望将case换成if / else链:

if a.is_a? String
  puts 'string'
elsif a.is_a?(Array) && a.all? { |obj| obj.is_a? String }
  puts 'an array with only string classes'
else
  raise ArgumentError, "unsupported object #{a}:#{a.class}"
end

或在案例条件内进行嵌套检查。但是然后您将有两个else状态,一个为if(表示它与数组大小写匹配,但并非所有字符串),另一个为case(表示这是其他东西)完全)。因此,我没有使用类似的错误处理代码,而是使用一个布尔变量来指示何时需要raise d错误:

ok = false
case a
 when String
  puts 'string'
  ok = true
 when Array
  if a.all? { |obj| obj.is_a? String }
    puts 'an array with only string classes'
    ok = true
  end
end
if !ok 
  raise ArgumentError, "unsupported object #{a}:#{a.class}"
end

答案 1 :(得分:0)

使用模式匹配!

a = ['one','twon']

case a
in String
  puts 'string'
in Array if a.all?(String)
  puts 'an array with only string classes'
else
  raise ArgumentError, "unsupported object #{a}:#{a.class}"
end

*红宝石2.7+
**实验功能