How to write a switch statement in Ruby
如何用Ruby编写switch语句?
Ruby使用
1 2 3 4 5 6 7 8 9 10 11 12 | 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 |
Ruby使用
这就允许了上述复杂的
与许多其他语言中的
处理类时,
该运算符按预期处理文本,但不处理类:
1 2 | 1 === 1 # => true Fixnum === Fixnum # => false |
这意味着,如果要对对象的类执行
1 2 3 4 5 6 7 8 9 | 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 |
将打印"它不是字符串"。
幸运的是,这很容易解决。已经定义了
1 | Fixnum === 1 # => true |
简而言之,可以通过删除
1 2 3 4 5 6 7 8 9 | 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完成的。另请参阅维基百科上的这篇文章。
引用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 |
另一个例子:
1 2 3 4 5 6 7 8 9 10 11 | 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编程语言(第1版,O'Reilly)的第123页(我使用的是Kindle)上,它说
案件…何时
要在查克的答案中添加更多示例:
带参数:
1 2 3 4 5 6 7 8 9 10 11 12 | 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 |
无参数:
1 2 3 4 5 6 7 8 | 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警告的问题。
许多编程语言,特别是那些从C派生的语言,都支持所谓的switch fallthrough。我在寻找在Ruby中实现这一点的最佳方法,并认为它可能对其他人有用:
在类C语言中,fallthrough通常如下所示:
1 2 3 4 5 6 7 8 9 10 11 | 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中,可以通过以下方式实现这一点:
1 2 3 4 5 6 | case expression when 'a', 'b', 'c' # Do something for a, b or c when 'd', 'e' # Do something else for d or e end |
这并不是完全等效的,因为不可能让
在Ruby2.0中,还可以在
1 2 3 4 5 6 7 | is_even = ->(x) { x % 2 == 0 } case number when 0 then puts 'zero' when is_even then puts 'even' else puts 'odd' end |
您还可以使用带有自定义
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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 |
(示例取自"Procs是否可以与Ruby2.0中的case语句一起使用?")
或者,有一个完整的类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 case语句的工作方式以及您可以使用它做什么"。)
可以使用正则表达式,例如查找字符串类型:
1 2 3 4 5 6 7 8 9 10 | 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的
如果您想知道如何在Ruby开关案例中使用或条件:
因此,在
1 2 3 4 | case car when 'Maruti', 'Hyundai' # Code here end |
使用Ruby case语句还可以做其他许多事情
它被称为
1 2 3 4 5 6 | case 5 when 5 puts 'yes' else puts 'else' end |
现在,为了好玩:
1 2 3 4 5 6 7 8 9 10 11 12 | case 5 # every selector below would fire (if first) when 3..7 # OK, this is nice when 3,4,5,6 # also nice when Fixnum # or when Integer # or when Numeric # or when Comparable # (?!) or when Object # (duhh) or when Kernel # (?!) or when BasicObject # (enough already) ... end |
结果表明,您也可以用
1 2 3 4 5 6 7 8 9 10 11 12 | case when x.nil? ... when (x.match /'^fn'/) ... when (x.include? 'substring') ... when x.gsub('o', 'z') == 'fnzrq' ... when Time.now.tuesday? ... end |
根据您的情况,您可能更喜欢使用方法散列。
如果有一个长的when's列表,并且每个when's都有一个要比较的具体值(而不是间隔),那么声明方法的散列,然后从散列中调用相关的方法会更有效。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # Define the hash menu = {a: :menu1, b: :menu2, c: :menu2, d: :menu3} # Define the methods def menu1 puts 'menu 1' end def menu2 puts 'menu 2' end def menu3 puts 'menu3' end # Let's say we case by selected_menu = :a selected_menu = :a # Then just call the relevant method from the hash send(menu[selected_menu]) |
多值时无值情况:
1 2 3 4 5 6 7 8 9 10 | 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 |
这里有一个正则表达式解:
1 2 3 4 5 6 7 8 9 10 | 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 |
由于
1 2 3 4 5 6 | puts case a when 0 "It's zero" when 1 "It's one" end |
Ruby使用
根据Ruby文档:
Case statements consist of an optional condition, which is in the
position of an argument tocase , and zero or morewhen clauses.
The firstwhen clause to match the condition (or to evaluate to
Boolean truth, if the condition is null)"wins", and its code stanza
is executed. The value of the case statement is the value of the
successfulwhen clause, ornil if there is no such clause.A case statement can end with an
else clause. Eachwhen a
statement can have multiple candidate values, separated by commas.
例子:
1 2 3 4 5 6 7 8 | case x when 1,2,3 puts"1, 2, or 3" when 10 puts"10" else puts"Some other number" end |
较短版本:
1 2 3 4 5 | case x when 1,2,3 then puts"1, 2, or 3" when 10 then puts"10" else puts"Some other number" end |
正如这篇由霍尼贝格撰写的博客所描述的,红宝石盒子;
可用于范围:
1 2 3 4 5 6 | case 5 when (1..10) puts"case statements match inclusion in a range" end ## =>"case statements match inclusion in a range" |
可与regex一起使用:
1 2 3 4 5 6 | case"FOOBAR" when /BAR$/ puts"they can match regular expressions!" end ## =>"they can match regular expressions!" |
可与Procs和Lambda一起使用:
1 2 3 4 5 6 | case 40 when -> (n) { n.to_s =="40" } puts"lambdas!" end ## =>"lambdas" |
此外,还可以与您自己的匹配类一起使用:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | class Success def self.===(item) item.status >= 200 && item.status < 300 end end class Empty def self.===(item) item.response_size == 0 end end case http_response when Empty puts"response was empty" when Success puts"response was a success" end |
您可以用Ruby以两种不同的方式编写case表达式。
第一条道路
1 2 3 4 5 6 7 8 9 | age = 20 case when age >= 21 puts"display something" when 1 == 0 puts"omg" else puts"default condition" end |
第二条道路
1 2 3 4 | case params[:unknown] when /Something/ then 'Nothing' when /Something else/ then 'I dont know' end |
你可以更自然地这样做,
1 2 3 4 5 6 7 8 | case expression when condtion1 function when condition2 function else function end |
很多很好的答案,但我想我会加上一个事实。如果您试图比较对象(类),请确保您有一个太空船方法(而不是一个笑话),或者了解它们是如何被比较的。
这里有一个关于这个话题的很好的讨论http://www.skorks.com/2009/09/ruby-equality-and-object-comparison/
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | 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 |
如上述许多答案中所述,==运算符在case/when语句的hood下使用。
这里有一些关于那个接线员的额外信息。
大小写相等运算符:===Ruby的许多内置类(如string、range和regexp)都提供了自己的==运算符实现,也称为case equality、triple equals或threeequals。因为它在每个类中的实现方式不同,所以根据调用对象的类型,它的行为会有所不同。通常,如果右边的对象"属于"或"是"左边的对象的成员,则返回true。例如,它可以用来测试对象是否是类(或其子类)的实例。
1 2 3 4 | String ==="zen" # Output: => true Range === (1..2) # Output: => true Array === [1,2,3] # Output: => true Integer === 2 # Output: => true |
同样的结果也可以通过其他可能最适合该工作的方法来实现,例如"是吗?"还有一个例子?.
范围实施===当对range对象调用==运算符时,如果右边的值在左边的范围内,则返回true。
1 2 3 4 5 6 | (1..4) === 3 # Output: => true (1..4) === 2.345 # Output: => true (1..4) === 6 # Output: => false ("a".."d") ==="c" # Output: => true ("a".."d") ==="e" # Output: => false |
请记住,==运算符调用左侧对象的==方法。所以(1..4)==3等于(1..4)==3。换句话说,左侧操作数的类将定义将调用==方法的哪个实现,因此操作数位置不能互换。
regexp的实现===如果右边的字符串与左边的正则表达式匹配,则返回true。/zen/="今日练习zazen"输出:=>真类似于"今天练习zazen"=~/zen/
上面两个例子之间唯一相关的区别是,当有匹配时,==返回true,=~返回整数,这是Ruby中的一个真实值。我们很快就会回到这里。
1 2 3 4 5 6 7 8 9 10 11 12 13 | $age = 5 case $age when 0 .. 2 puts"baby" when 3 .. 6 puts"little child" when 7 .. 12 puts"child" when 13 .. 18 puts"youth" else puts"adult" end |
参考=>https://www.tutorialspoint.com/ruby/rubyu ifu else.htm
我们可以为多个条件编写switch语句。
例如,
1 2 3 4 5 6 7 8 9 | x = 22 CASE x WHEN 0..14 THEN puts"#{x} is less than 15" WHEN 15 THEN puts"#{x} equals 15" WHEN 15 THEN puts"#{x} equals 15" WHEN 15..20 THEN puts"#{x} is greater than 15" ELSE puts"Not in the range, value #{x}" END |
在您的环境中不支持正则表达式?例如Shopify脚本编辑器(2018年4月):
[Error]: uninitialized constant RegExp
以下方法组合的解决方案已经在这里和这里介绍过:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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 |
我在类方法语句中使用了
我开始使用:
1 2 3 4 5 6 7 8 9 | a ="secondcase" var_name = case a when"firstcase" then"foo" when"secondcase" then"bar" end puts var_name >>"bar" |
在某些情况下,它有助于压缩代码。
在when子句中强调逗号","是if语句的一个,这很重要,也就是说,它在when子句的定界表达式之间进行OR比较,而不是AND比较。所以请检查下面的case语句。显然,x不小于2,但返回值是'apple'。为什么?因为x是3,并且由于','作为一个,所以不需要计算表达式'x<2'。
1 2 3 4 5 6 | x = 3 case x when 3, x < 2 then 'apple' when 3, x > 2 then 'orange' end =>"apple" |
您可能认为要执行和,可以在下面这样做。但它不起作用。这是因为(3&x>2)的计算结果是真的,Ruby接受真值并将其与x进行比较,得出的值为==,显然不是真的,因为x是3。
1 2 3 4 5 | case x when (3 && x < 2) then 'apple' when (3 && x > 2) then 'orange' end => nil |
要进行比较,您必须像对待病例一样对待,否则将阻止:
1 2 3 4 | case when x == 3 && x < 2 then 'apple' when x == 3 && x > 2 then 'orange' end |
在Ruby编程语言书中,Matz说后一种形式是简单(并且很少使用)的形式,它只是if/elsif/else的一种可选语法。但是,无论它是否经常使用,我都看不到为给定的"when"子句附加多个表达式的任何其他方法。