when - ruby case语句




如何在Ruby中编写switch语句? (14)

我如何在Ruby中编写switch语句?


情况......当

为了给查克的答案增加更多的例子:

带参数:

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使用这种case编写switch语句。

根据Ruby文档

案例陈述由一个可选条件组成,该条件位于case参数的位置,并且when子句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这篇博客描述了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

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

如上所述,这允许复杂的子句。 可以测试范围,类和各种事物,而不仅仅是平等。

与许多其他语言中的switch语句不同,Ruby的case并没有出现fall-through ,所以在break when不需要结束每个语句。 您也可以在单个when子句中指定多个匹配项,例如when "foo", "bar"


不支持您环境中的正则表达式? 例如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? 。 如果你是一个ruby-nazi ,请想象我使用了这个(item.include? 'A') || ... 相反。 repl.it测试。


在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轻松创建自己的比较器

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案例声明的工作原理和你能做什么 ”的例子。)


多值时和不值值情况:

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

它被称为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参数来替换一个任意的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


您可以用两种不同的方式在ruby中编写case表达式。

  1. 类似于一系列“if”陈述
  2. 指定案例旁边的目标,并将每个“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

我已经开始使用:

a = "secondcase"

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

puts var_name
>> "bar"

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


正如上面的许多答案所述,===操作符在case / when语句的底层使用。

以下是关于该操作员的一些额外信息。

案例相等运算符:===

许多Ruby的内置类(如String,Range和Regexp)提供了===运算符的自己实现,也称为case-equality,triple equals或threequals。 因为它在每个类中的实现方式不同,所以它的行为将有所不同,具体取决于所调用对象的类型。 通常,如果右侧的对象“属于”或“是左侧的对象的成员”,则返回true。 例如,它可以用来测试一个对象是否是一个类的实例(或它的一个子类)。

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.换句话说,左边操作数的类将定义===方法的实现是称为,所以操作数位置不可互换。

正则表达式实现===

如果右侧的字符串与左侧的正则表达式匹配,则返回true。 / zen / ===“今天练习zazen”#输出:=> true#与“今日练习zazen”类似=〜/ zen /

上面两个例子唯一相关的区别是,当匹配时,===返回true,并且=〜返回一个整数,这是Ruby中的一个真值。 我们会尽快回复。


由于switch case总是返回一个对象,我们可以直接打印它的结果:

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

这是通过Ruby中的case完成的。 另请参阅维基百科上的这篇文章

引:

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 Programming Lanugage (第1版,O'Reilly)的第123页(我正在使用Kindle)中,它表示when子句后面的then关键字可以用换行符或分号替换(就像在if then else语句的if then else语法中一样)。 (Ruby 1.8也允许冒号代替...但是这个语法在Ruby 1.9中不再允许。)






conditional