如何在Ruby中编写switch语句

这篇博客介绍了如何在Ruby中使用switch语句,包括正则表达式和范围的实现,以及与if...else语句的比较。文章详细探讨了Ruby的`case`语句,提供了多种使用案例,强调了`===`运算符的作用,并提到了在不同情况下的使用技巧。
摘要由CSDN通过智能技术生成

如何在Ruby中编写switch语句?


#1楼

案例...当

Chuck的答案中添加更多示例:

带参数:

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中编写switch语句 ”。


#2楼

您可以使用正则表达式,例如查找字符串类型:

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示例(不带参数)完成此操作,只有这种方法对于此类情况更干净。


#3楼

在Ruby 2.0中,您还可以在case语句中使用lambda,如下所示:

is_even = ->(x) { x % 2 == 0 }

case number
when 0 then puts 'zero'
when is_even then puts 'even'
else puts 'odd'
end

您还可以使用带有自定义===的Struct轻松创建自己的比较器

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是否可以与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语句如何工作以及您可以如何使用它 ”。)


#4楼

很多很好的答案,但我想我会添加一个事实。.如果您尝试比较对象(类),请确保您具有太空飞船方法(不是开玩笑)或了解如何比较它们

Ruby的平等和对象比较 ”是对该主题的一个很好的讨论。


#5楼

由于switch case始终返回单个对象,因此我们可以直接打印其结果:

puts case a
     when 0
        "It's zero"
     when 1
        "It's one"
     end

#6楼

许多编程语言(尤其是从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'之前执行一段代码,但是在大多数情况下,我发现它足够相似,可以用相同的方式使用。


#7楼

多值时间和无值情况:

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

#8楼

如果您想知道如何在Ruby转换案例中使用OR条件:

所以,在一个case声明,一,是相当于||if语句中。

case car
   when 'Maruti', 'Hyundai'
      # Code here
end

请参阅“ Ruby Case语句如何工作以及如何使用它 ”。


#9楼

我已经开始使用:

a = "secondcase"

var_name = case a
  when "firstcase" then "foo"
  when "secondcase" then "bar"
end

puts var_name
>> "bar"

在某些情况下,它有助于压缩代码。


#10楼

根据您的情况,您可能更喜欢使用方法的哈希。

如果有一个长的列表when S和他们每个人都有一个具体的数值与(不是间隔)进行比较,这将是更有效的申报方法的哈希,然后调用从这样的散列的相关方法。

# 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])

#11楼

这就是所谓的case ,它的工作原理与您预期的一样,外加===更多有趣内容,它们实现了测试。

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

事实证明,您还可以通过省略初始case参数并只编写第一个匹配项的表达式来替换case的任意if / else链(即,即使测试不涉及公共变量)想。

case
  when x.nil?
    ...
  when (x.match /'^fn'/)
    ...
  when (x.include? 'substring')
    ...
  when x.gsub('o', 'z') == 'fnzrq'
    ...
  when Time.now.tuesday?
    ...
end

#12楼

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

#13楼

您可以更自然地做到这一点,

case expression
when condtion1
   function
when condition2
   function
else
   function
end

#14楼

如以上许多答案所述,在case / when语句的===使用===运算符。

这是有关该运算符的其他信息:

大小写相等运算符: ===

Ruby的许多内置类(例如String,Range和Regexp)提供自己的===运算符的实现,也称为“大小写相等”,“三等号”或“三等号”。 由于在每个类中实现的方式不同,因此根据调用对象的类型,其行为也将有所不同。 通常,如果右侧的对象“属于”左侧的对象或属于左侧的对象,则返回true。 例如,它可以用来测试一个对象是否是一个类(或其子类之一)的实例。

String === "zen"  # Output: => true
Range === (1..2)   # Output: => true
Array === [1,2,3]   # Output: => true
Integer === 2   # Output: => true

使用其他可能最适合该工作的方法(例如is_a?可以达到相同的结果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 。 换句话说,左侧操作数的类将定义将调用===方法的哪种实现,因此操作数位置不可互换。

正则表达式的===实现

如果右侧的字符串与左侧的正则表达式匹配,则返回true。

/zen/ === "practice zazen today"  # Output: => true
# is similar to
"practice zazen today"=~ /zen/

上面两个示例之间唯一相关的区别是,如果存在匹配项,则===返回true,而=~返回整数,这是Ruby中的真实值。 我们将尽快回到这一点。


#15楼

Ruby使用这种case来编写switch语句。

根据case文档:

Case语句由一个可选条件组成,该条件位于case参数的位置,并且零个或多个when子句。 第一个与条件匹配的when子句(如果条件为null,则为布尔真值)将“获胜”,并执行其代码节。 case语句的值是成功的when子句的值;如果没有这样的子句,则为nil

case语句可以以else子句结尾。 每次when一份声明中可以有多个候选值,用逗号分隔。

例:

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

正如“ Ruby的案例陈述-高级技术 ”所描述的Ruby case ;

可以与Ranges一起使用:

case 5
when (1..10)
  puts "case statements match inclusion in a range"
end

## => "case statements match inclusion in a range"

可以与Regex一起使用:

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

#16楼

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

  1. 类似于一系列的if语句
  2. case旁边指定一个目标,并将每个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

#17楼

$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

有关更多信息请参见“ Ruby-if ... else,case,除非 ”。


#18楼

您的环境中不支持正则表达式? 例如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 s,因为|| 具有比.include?更高的优先级.include? 。 如果您是红宝石 (item.include? 'A') || ... ,请想象我使用了这个(item.include? 'A') || ... (item.include? 'A') || ...代替。 repl.it测试。


#19楼

我们可以为多个条件编写switch语句。

例如,

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

#20楼

when子句中强调逗号( , )是至关重要的。 它充当|| if语句的意思是,它在when子句的定界表达式之间进行“ 或”比较而不是“ 与”比较。 请参阅以下案例声明:

x = 3
case x
  when 3, x < 2 then 'apple'
  when 3, x > 2 then 'orange'
end
 => "apple"

x不小于2,但返回值为"apple" 。 为什么? 因为x为3,并且由于',`` acts as an || , it did not bother to evaluate the expression x <2'。

您可能会认为要执行AND ,您可以在下面执行类似的操作,但这不起作用:

case x
  when (3 && x < 2) then 'apple'
  when (3 && x > 2) then 'orange'
end
 => nil 

这是行不通的,因为(3 && x > 2)计算结果为true,而Ruby获取True值,并使用===将其与x进行比较,这是不正确的,因为x为3。

要进行&&比较,您必须将case视为if / else块:

case
  when x == 3 && x < 2 then 'apple'
  when x == 3 && x > 2 then 'orange'
end

Matz在Ruby Programming Language一书中说,后一种形式是简单的(且不经常使用)形式,无非是if / elsif / else的替代语法。 但是,无论是否经常使用它,对于给定的when子句,我看不到任何其他方式附加多个&&表达式。


#21楼

case...when处理类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 or number')
end

将打印“不是字符串或数字”。

幸运的是,这很容易解决。 已定义===运算符,以便在将其与一个类一起使用并提供该类的实例作为第二个操作数时返回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 or number')
end

我今天在寻找答案时遇到了这个问题,这是第一个出现的页面,因此我认为它对处于相同情况的其他人很有用。


#22楼

case语句运算符就像其他语言中的switch一样。

这是C语言中switch...case的语法:

switch (expression)
​{
    case constant1:
      // statements
      break;
    case constant2:
      // statements
      break;
    .
    .
    .
    default:
      // default statements
}

这是case...when的语法case...when在Ruby中时:

case expression
  when constant1, constant2 #Each when statement can have multiple candidate values, separated by commas.
     # statements 
     next # is like continue in other languages
  when constant3
     # statements 
     exit # exit is like break in other languages
  .
  .
  .
  else
     # statements
end

例如:

x = 10
case x
when 1,2,3
  puts "1, 2, or 3"
  exit
when 10
  puts "10" # it will stop here and execute that line
  exit # then it'll exit
else
  puts "Some other number"
end

有关更多信息,请参见case文档。


#23楼

这是通过在Ruby中使用case来完成的。 另请参阅Wikipedia上的“ Switch语句 ”。

引:

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

在我的Kindle上的《 Ruby编程语言》 (第1版,O'Reilly)的第123页左右,它说了when子句后面的then关键字可以用换行符或分号代替(就像if then else语法一样)。 (Ruby 1.8还允许使用冒号代替then ,但是Ruby 1.9中不再允许使用此语法。)


#24楼

Ruby使用case表达式代替。

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使用===运算符将when子句中的对象与case子句中的对象进行比较。 例如, 1..5 === x ,而不是x === 1..5

如上所述,这可以实现复杂的when子句。 可以测试范围,类和各种各样的东西,而不仅仅是相等性。

不像switch在许多其他语言的语句,Ruby的case并没有落空 ,所以没有必要每次结束whenbreak 。 您还可以在单​​个when子句中指定多个匹配项,例如when "foo", "bar"

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值