首页 文章

如何在Ruby中编写switch语句

提问于
浏览
1878

如何在Ruby中编写switch语句?

21 回答

  • 89

    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
    

    将打印“它不是一个字符串” .

    幸运的是,这很容易解决 . 已定义 === 运算符,以便在将其与类一起使用时返回 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
    

    我今天在寻找答案时遇到了这个问题,这是第一个出现的页面,所以我认为在同样的情况下对其他人有用 .

  • 65

    它由Ruby中的case完成 . 另见this article on Wikipedia .

    引:

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

  • 8

    我已经开始使用:

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

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

  • 49

    许多编程语言,特别是那些从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' 执行一个代码块,但是在大多数情况下我发现它类似于以相同的方式有用 .

  • 25

    您可以在ruby中以两种不同的方式编写案例表达式 .

    • 类似于一系列"if"语句

    • 指定案例旁边的目标,并将每个"when"子句与目标进行比较 .

    1 st方式

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

    2 nd方式

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

    很多很好的答案,但我想我会添加一个factoid ..如果你试图比较对象(类)确保你有一个太空船方法(不是一个笑话)或理解他们如何被比较

    以下是关于该主题的一个很好的讨论http://www.skorks.com/2009/09/ruby-equality-and-object-comparison/

  • 11

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

    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 Operators” . 这也可以使用@mmdemirbas示例(不带参数)来完成,只有这种方法对于这些类型的情况更清晰 .

  • 5

    正如上面的许多答案中所述,= case运算符在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.换句话说,左操作数的类将定义===方法的哪个实现将是调用,因此操作数位置不可互换 .

    Regexp执行===

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

    上面两个例子之间唯一相关的区别是,当匹配时,===返回true而= =返回一个整数,这是Ruby中的真值 . 我们很快就会回到这里 .

  • 2385

    你可以用更自然的方式做到这一点,

    case expression
    when condtion1
       function
    when condition2
       function
    else
       function
    end
    
  • 67

    您的环境中不支持正则表达式?例如 . Shopify Script Editor(2018年4月):

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

    here和之前已经涵盖的方法组合之后的解决方法here

    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 ,因为 || 的优先级高于 .include? . 如果你是ruby-nazi,请想象我使用了这个 (item.include? 'A') || ... . repl.it测试 .

  • 8

    多值时和无值情况:

    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
    

    这里有一个regular expression解决方案:

    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
    
  • 403

    案例......何时

    要向Chuck's answer添加更多示例:

    With parameter:

    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
    

    Without parameter:

    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警告the issue .

  • 0

    Ruby使用 case 来编写switch语句 .

    根据Ruby Docs

    Case语句由一个可选条件组成,该条件位于case的参数位置,并且在子句时为零或更多 . 匹配条件的第一个when子句(或者,如果条件为null,则评估为布尔真值)“wins”,并执行其代码节 . 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 and 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
    
  • 4
    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
    
  • 193

    它被称为 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 参数并只写第一个匹配就是你的表达式想 .

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

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

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

    在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
    

    (示例取自“Can procs be used with case statements in Ruby 2.0?” . )

    或者,完整的课程:

    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
    

    (例子来自“How A Ruby Case Statement Works And What You Can Do With It” . )

  • 19

    Ruby使用case expression代替 .

    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 没有fall-through,因此不需要使用 break 结束每个 when . 您还可以在单个 when 子句中指定多个匹配项,例如 when "foo", "bar" .

  • 19
    $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
    

    reference => https://www.tutorialspoint.com/ruby/ruby_if_else.htm

  • 1

    如果您渴望知道如何在Ruby switch案例中使用OR条件:

    因此,在 case 语句中, ,if 语句中等同于 || .

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

    Many other things you can do with a Ruby case statement

  • 2

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

    如果有一个很长的时间列表,并且每个都有一个具体的值来比较(而不是间隔),那么声明方法的散列然后从这样的散列调用相关方法会更有效 .

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

相关问题