如何在Ruby中编写一个switch语句
如何在Ruby中编写switch语句?
Ruby使用case
expression式 。
case a 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 #{a} -- I have no idea what to do with that." end
比较是通过使用===
运算符将when-clause中的对象与case-clause中的对象进行比较来完成的。 也就是说,它是1..5 === a
和String === a
,而不是a === 1..5
。 这允许你在上面看到复杂的语义,在这里你可以使用范围和类以及各种各样的东西,而不仅仅是testing相等性。
与许多其他语言的switch语句不同的是,Ruby的case
并没有发生,所以when
break
when
不需要结束。 而是像when "foo", "bar"
那样为单个指定多个匹配。
case...when
处理类时有点意外。 这是由于它使用===
运算符。
该操作符按照预期的方式工作,但不能用类:
1 === 1 # => true Fixnum === Fixnum # => false
这意味着如果你想做一个case ... when
一个对象的类,这不会工作:
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
将打印“这不是一个string”。
幸运的是,这很容易解决。 ===
运算符已被定义,所以如果你在一个类中使用它,并且提供这个类的一个实例作为第二个操作数,它将返回true
Fixnum === 1 # => true
总之,上面的代码可以通过删除.class
来修复:
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 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
另一个例子:
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 Programming第一版(O'Reilly)的第123页(我正在使用Kindle)上,它说when
子句后面的then
关键字可以用换行符或分号代替(就像if then else
语法)。 (Ruby 1.8也允许冒号代替…但是这个语法在Ruby 1.9中不再允许。)
情况……当
为了给查克的答案增加更多的例子:
带参数:
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
没有参数:
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警告的问题 。
在Ruby 2.0中,你也可以在case
语句中使用lambdas,如下所示:
is_even = ->(x) { x % 2 == 0 } case number when 0 then puts 'zero' when is_even then puts 'even' else puts 'odd' end
您还可以使用具有自定义===
的Struct来轻松创build自己的比较器
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
(取自“ 可以在Ruby 2.0中使用case语句吗? ”)
或者,完整的课程:
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语句如何工作以及如何处理 ”)。
许多编程语言,尤其是那些从C派生的编程语言,都支持所谓的Switch Fallthrough 。 我正在寻找在Ruby中做同样的事情的最佳方式,并认为这可能对其他人有用:
在C语言的语言中,fallthrough通常看起来像这样:
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
这并不完全等价,因为在'b'
或'c'
之前不能让'a'
执行一段代码,但是大多数情况下,我发现它的相似性足以以相同的方式有用。
您可以使用正则expression式,例如查找stringtypes:
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的case
会使用相等操作数===
(谢谢@JimDeville)。 更多信息可在“ Ruby运营商 ”处获得。 这也可以使用@mmdemirbas示例(不带参数)来完成,只有这种方法对于这些types的案例来说是更清晰的。
如果您渴望知道如何在Ruby开关的情况下使用OR条件:
所以,在一个case
语句中,a是||
的等价物 在if
语句中。
case car when 'Maruti', 'Hyundai' # Code here end
Ruby case语句可以做很多其他事情
这就是所谓的case
,它的工作方式就像你所期望的,再加上更多有趣的东西礼貌===
实现testing。
case 5 when 5 puts 'yes' else puts 'else' end
现在有一些乐趣:
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
而事实certificate,你也可以通过忽略初始case
参数来replace一个任意的if / else链(也就是说,即使这些testing不涉及一个公共variables),只需要写第一个匹配的expression式即可想。
case when x.nil? ... when (x.match /'^fn'/) ... when (x.include? 'substring') ... when x.gsub('o', 'z') == 'fnzrq' ... when Time.now.tuesday? ... end
由于switch case
总是返回一个对象,所以我们可以直接打印它的结果:
puts case a when 0 "It's zero" when 1 "It's one" end
多值时和无值情况:
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
以下是一个正则expression式解决scheme
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
根据你的情况,你可能更喜欢使用方法的散列。
如果有一个长的列表,并且每个列表都有一个与(不是间隔)比较的具体值,那么声明一个方法的哈希值,然后像这样从哈希中调用相关的方法会更有效。
# 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])
Ruby使用这种case
来编写switch语句。
根据Ruby Docs :
Case语句由一个可选的条件组成,该条件位于
case
的参数的位置,when
从句的位置是零个或多个。 第一个when
子句匹配条件(或者评估为布尔真值,如果条件为空)“胜出”,并且其代码段被执行。 case语句的值是when
子句的成功值,如果没有这个子句,则为nil
。case语句可以以
else
子句结束。 每个语句可以有多个候选值,用逗号分隔。
例:
case x when 1,2,3 puts "1, 2, or 3" when 10 puts "10" else puts "Some other number" end
更短的版本:
case x when 1,2,3 then puts "1, 2, or 3" when 10 then puts "10" else puts "Some other number" end
正如Honeybadger的博客所描述的那样,
可以与范围一起使用:
case 5 when (1..10) puts "case statements match inclusion in a range" end ## => "case statements match inclusion in a range"
可以和正则expression式一起使用:
case "FOOBAR" when /BAR$/ puts "they can match regular expressions!" end ## => "they can match regular expressions!"
可以和Procs和Lambdas一起使用:
case 40 when -> (n) { n.to_s == "40" } puts "lambdas!" end ## => "lambdas"
另外,可以使用你自己的比赛类:
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中用两种不同的方式编写caseexpression式。
- 类似于一系列的“if”语句
- 在案例旁边指定一个目标,并将每个“when”子句与目标进行比较。
第一种方式
age = 20 case when age >= 21 puts "display something" when 1 == 0 puts "omg" else puts "default condition" end
第二种方式
case params[:unknown] when /Something/ then 'Nothing' when /Something else/ then 'I dont know' end
很多很好的答案,但我想我会添加一个factoid。如果你正在试图比较对象(类),确保你有一个太空船的方法(而不是一个笑话),或了解他们如何比较
这是一个很好的讨论主题http://www.skorks.com/2009/09/ruby-equality-and-object-comparison/
你可以用更自然的方式做到这一点,
case expression when condtion1 function when condition2 function else function end
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语句的底层使用。
以下是关于该操作员的一些额外信息。
案例相等运算符:===
许多Ruby的内置类(如String,Range和Regexp)提供了===运算符(也称为case-equality,triple equals或threequals)的自己的实现。 因为它在每个类中都以不同的方式实现,所以它将根据所调用的对象的types而有所不同。 通常,如果右侧的对象“属于”或“是左侧的对象的成员”,则返回true。 例如,它可以用来testing一个对象是否是一个类的实例(或者它的一个子类)。
String === "zen" # Output: => true Range === (1..2) # Output: => true Array === [1,2,3] # Output: => true Integer === 2 # Output: => true
其他可能最适合这项工作的方法也可以达到同样的结果,如is_a? 和instance_of ?.
===的范围实现
当在范围对象上调用===运算符时,如果右边的值落在左边的范围内,则返回true。
(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.换句话说,左边操作数的类将定义===方法的实现是所谓的操作数位置是不可互换的。
正则expression式实现===
如果右侧的string与左侧的正则expression式匹配,则返回true。 / zen / ===“今天练习zazen”#输出:=> true#类似于“今天的练习zazen”=〜/ zen /
上面两个例子唯一相关的区别是,当匹配时,===返回true,并且=〜返回一个整数,这是一个Ruby中的真值。 我们会很快回到这个。
我已经开始使用:
a = "secondcase" var_name = case a when "firstcase" then "foo" when "secondcase" then "bar" end puts var_name >> "bar"
在某些情况下它有助于压缩代码。
$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