如何在Ruby中编写switch语句?


当前回答

许多编程语言,特别是源于C的语言,都支持所谓的Switch Fallthrough。我正在寻找在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”之前执行一块代码,但在大多数情况下,我发现它足够相似,以同样的方式有用。

其他回答

Ruby在2.7中引入了模式匹配

这是一个超级强大的功能

它也使用case,但有另一种语法

还有查找模式功能

users =
  { users:
    [
      { user: 'user', email: 'user@user.com' },
      { user: 'admin', email: 'admin@admin.com' },
    ]
  }

case users
in users: [*, { user:, email: /admin/ => admin_email }, *]
  puts admin_email
else
  puts "No admin"
end

# will print admin@admin.com

与通常情况不同,如果条件不匹配,将抛出NoMatchingPatternError。所以你可能不得不使用else分支

puts "Recommend me a language to learn?"
input = gets.chomp.downcase.to_s

case input
when 'ruby'
    puts "Learn Ruby"
when 'python'
    puts "Learn Python"
when 'java'
    puts "Learn Java"
when 'php'
    puts "Learn PHP"
else
    "Go to Sleep!"
end

在您的环境中不支持正则表达式?例如,Shopify脚本编辑器(2018年4月):

[错误]:未初始化常量RegExp

一种变通方法,结合了前面在这里和这里介绍过的方法:

code = '!ADD-SUPER-BONUS!'

class StrContains
  def self.===(item)
    item.include? 'SUPER' or item.include? 'MEGA' or\
    item.include? 'MINI' or item.include? 'UBER'
  end
end

case code.upcase
when '12345PROMO', 'CODE-007', StrContains
  puts "Code #{code} is a discount code!"
when '!ADD-BONUS!'
  puts 'This is a bonus code!'
else
  puts 'Sorry, we can\'t do anything with the code you added...'
end

我在类方法语句中使用了or,因为||的优先级高于包括

如果您仍然喜欢使用||,即使在这种情况下或更可取,也可以改为使用:(item.include?“A”)||。。。。您可以在这个repl.it中测试它。

多值时和无值情况:

print "Enter your grade: "
grade = gets.chomp
case grade
when "A", "B"
  puts 'You pretty smart!'
when "C", "D"
  puts 'You pretty dumb!!'
else
  puts "You can't even use a computer!"
end

这里有一个正则表达式解决方案:

print "Enter a string: "
some_string = gets.chomp
case
when some_string.match(/\d/)
  puts 'String has numbers'
when some_string.match(/[a-zA-Z]/)
  puts 'String has letters'
else
  puts 'String has no numbers or letters'
end

在Ruby中,可以用两种不同的方式编写case表达式:

类似于一系列if语句在case旁边指定一个目标,并将每个when子句与目标进行比较。

age = 20
case 
when age >= 21
puts "display something"
when 1 == 0
puts "omg"
else
puts "default condition"
end

or:

case params[:unknown]
when /Something/ then 'Nothing'
when /Something else/ then 'I dont know'
end