代码之家  ›  专栏  ›  技术社区  ›  Joe Holloway

如何在Ruby中编写switch语句

  •  2285
  • Joe Holloway  · 技术社区  · 17 年前

    我该怎么写 switch Ruby中的声明?

    28 回复  |  直到 6 年前
        1
  •  2824
  •   DTavaszi    8 年前

    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 带有object的子句 案件 条款使用 === 操作员。例如, (1..5) === x ,而不是 x === (1..5) .

    这允许复杂 当 如上所述的条款。可以测试范围、类和各种事物,而不仅仅是相等性。

    不像 switch 许多其他语言的语句,Rubys 案件 没有 fall-through ,所以没有必要结束每一个 当 break 。您还可以在单个文件中指定多个匹配项 当 类似子句 when "foo", "bar" .

        2
  •  463
  •   kikito    5 年前

    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 从 case obj.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
    

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

        3
  •  231
  •   nonopolarity    6 年前

    它是使用 case Switch statement “在维基百科上。

    引用:

    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
    

    第123页左右 (第一版,O'Reilly)在我的Kindle上,上面写着 then 关键字跟在后面 when 子句可以用换行符或分号替换(就像在 if then else 语法)。(Ruby 1.8也允许用冒号代替 ,但Ruby 1.9中不再允许这种语法。)

        4
  •  111
  •   the Tin Man    6 年前

    案件。..何时

    添加更多示例 Chuck's answer :

    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
    

    How to write a switch statement in Ruby 基基托警告说。

        5
  •  80
  •   Community Mohan Dere    9 年前

    在Ruby 2.0中,您还可以在 case 声明如下:

    is_even = ->(x) { x % 2 == 0 }
    
    case number
    when 0 then puts 'zero'
    when is_even then puts 'even'
    else puts 'odd'
    end
    

    ===

    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 ".)

        6
  •  79
  •   Robert Kajic    10 年前

    许多编程语言,特别是从C派生的编程语言,都支持所谓的 Switch Fallthrough 。我在Ruby中寻找做同样事情的最佳方法,并认为它可能对其他人有用:

    在类C语言中,fall-through通常看起来像这样:

    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
  •  53
  •   the Tin Man    13 年前

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

    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 将使用相等操作数 === Ruby Operators “。这也可以使用@mmdemirbas示例(不带参数)来完成,只是这种方法对这些类型的情况更干净。

        8
  •  37
  •   DigitalRoss    9 年前

    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
      when x.nil?
        ...
      when (x.match /'^fn'/)
        ...
      when (x.include? 'substring')
        ...
      when x.gsub('o', 'z') == 'fnzrq'
        ...
      when Time.now.tuesday?
        ...
    end
    
        9
  •  33
  •   the Tin Man    6 年前

    如果你想知道如何在Ruby开关中使用OR条件:

    所以,在a case 声明,a , || 在一个 if 声明。

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

    请参阅“ How A Ruby Case Statement Works And What You Can Do With It

        10
  •  25
  •   the Tin Man    6 年前

    Ruby使用 case 用于编写switch语句。

    case 文档:

    Case语句由一个可选条件组成,该条件位于 论点的立场 案件 when 条款。 第一 当 布尔真值(如果条件为空)获胜,其代码段 被执行。案例陈述的价值是 成功的 当 条款,或 nil 如果没有这样的条款。

    案例陈述可以以 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
    

    作为“ Ruby's case statement - advanced techniques “描述Ruby 案件 ;

    可与 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
    
        11
  •  22
  •   the Tin Man    6 年前

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

    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])
    
        12
  •  21
  •   Peter Mortensen Pieter Jan Bonestroo    11 年前

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

    puts case a
         when 0
            "It's zero"
         when 1
            "It's one"
         end
    
        13
  •  20
  •   Peter Mortensen Pieter Jan Bonestroo    11 年前

    多值时和无值情况:

    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
    

    还有a 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
    
        14
  •  14
  •   the Tin Man    6 年前

    你可以写 case Ruby中有两种不同的表达式:

    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
    
        15
  •  11
  •   Navin    10 年前

    你可以用更自然的方式这样做,

    case expression
    when condtion1
       function
    when condition2
       function
    else
       function
    end
    
        16
  •  9
  •   the Tin Man    6 年前

    答案很多,但我想补充一个事实。。如果你试图比较对象(类),请确保你有一个太空船方法(不是笑话)或了解它们是如何被比较的

    " Ruby Equality And Object Comparison “是关于这个话题的一个很好的讨论。

        17
  •  8
  •   Community Mohan Dere    6 年前

    正如上述许多答案所述 === case / when 声明。

    以下是关于该运营商的更多信息:

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

    === 运算符,也称为“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? .

    范围实施 ===

    时中 === 对range对象调用运算符,如果右侧的值落在左侧的范围内,则返回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/ === "practice zazen today"  # Output: => true
    # is similar to
    "practice zazen today"=~ /zen/
    

    === 返回true和 =~ 返回一个整数,这是Ruby中的真值。我们很快就会回到这个问题上。

        18
  •  5
  •   Prabhakar    10 年前

    case x
    when 1..5
      "It's between 1 and 5"
    when 6
      "It's 6"
    when 7..1.0/0
      "It's equal or greater than 7"
    when -1.0/0..0
      "It's equal or less than 0"
    end
    

    1.0/0 等于 Float::INFINITY ,所以你可以使用你喜欢的。

    你可以使用 Endless Ranges , Ruby 2.7之后 您还可以使用 Beginless Ranges ,因此您可以执行以下操作:

    case x
    when 1..5
      "It's between 1 and 5"
    when 6
      "It's 6"
    when (7..)
      "It's equal or greater than 7"
    when (..0)
      "It's equal or less than 0"
    end
    
        19
  •  4
  •   Peter Mortensen Pieter Jan Bonestroo    11 年前
    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
    
        20
  •  4
  •   the Tin Man    6 年前

    我已经开始使用:

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

        21
  •  3
  •   the Tin Man    6 年前
    $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, unless “了解更多信息。

        22
  •  3
  •   CPHPython    6 年前

    , )在a when 条款。它作为一个 || a if 或 与 分隔表达式之间的比较 当 条款。见以下案例说明:

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

    x "apple" 为什么?因为 X 3岁以后 ',`` acts as an , it did not bother to evaluate the expression

    你可能会认为表演 与 ,你可以做下面这样的事情,但它不起作用:

    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 像一个 如果 / else

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

    在《Ruby编程语言》一书中,Matz说后一种形式是简单(且不常用)的形式,它只不过是 如果 / elsif / 否则 。但是,无论它是否不常使用,我都看不到任何其他方式来附加多个 && 给定表达式 当 条款。

        23
  •  1
  •   Vikrant Mayank    7 年前

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

    正则表达式

    在前面介绍的方法组合之后的解决方法 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 s在类方法语句中,因为 || .include? .

    如果您仍然喜欢使用 || , even though or is preferable in this case (item.include? 'A') || ... . 你可以在这里测试它 repl.it .

        24
  •  1
  •   the Tin Man    6 年前

    这 case 语句运算符类似 switch 在其他语言中。

    这是以下语法 switch...case

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

    这是以下语法 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 文档。

        25
  •  1
  •   Paulo Belo    5 年前

    我们可以为多种条件编写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
    
        26
  •  0
  •   AlexSh    5 年前

    Ruby支持case表达式。

    case e = StandardError.new("testing")
    when Exception then puts "error!"
    else puts "ok!"
    end # => error! 
    

    多值匹配:

    case 3
    when 1,2,3 then puts "1..3"
    when 4,5,6 then puts "4..6"
    else puts "?"
    end # => 1..3
    

    正则表达式评估:

    case "monkey"
    when /mon/ then puts "banana"
    else puts "?" 
    end # => banana
    
        27
  •  0
  •   Moriarty    5 年前

    Ruby介绍 pattern matching

    这是一个超级强大的功能

    它还使用 case ,但有另一种语法

    还有查找模式功能

    users =
      { users:
        [
          { user: 'user', email: 'user@user.com' },
          { user: 'admin', email: 'admin@admin.com' },
        ]
      }
    
    case users
    in users: [*, { user:, email: /admin/ => admin_email }, *]
      puts admin_email
    else
      puts "No admin"
    end
    
    # will print admin@admin.com
    

    与往常不同 案件 如果条件不匹配, NoMatchingPatternError 将被抛出。因此,您可能需要使用 else 分支