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

如何在Ruby中编写switch语句

  •  1911
  • Joe Holloway  · 技术社区  · 15 年前

    我该如何写一篇文章 switch Ruby中的语句?

    22 回复  |  直到 5 年前
        1
  •  2824
  •   DTavaszi    6 年前

    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 案例 使用 === 操作人员例如 1..5 === x ,而不是 x === 1..5 .

    这使得复杂的 什么时候 上述条款。范围、类别和各种各样的东西都可以测试,而不仅仅是平等性。

    不像 switch 许多其他语言的语句,Rubys 案例 没有 fall-through ,因此没有必要结束每一次 用一个 break . 您还可以在一个数据库中指定多个匹配项 子句式 when "foo", "bar" .

        2
  •  463
  •   kikito    3 年前

    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    5 年前

    它是使用 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
    

    (第一版,O'Reilly)在我的Kindle上,上面写着 then 关键字后面的 when 子句可以替换为换行符或分号(就像 if then else 语法)。(Ruby 1.8还允许冒号代替 然后

        4
  •  111
  •   the Tin Man    5 年前

    什么时候

    添加更多示例到 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 “kikito对此提出了警告。

        5
  •  80
  •   Community SushiHangover    7 年前

    在Ruby 2.0中,还可以在中使用lambdas 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    8 年前

    许多编程语言,特别是从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
  •  53
  •   the Tin Man    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
    

    鲁比的 case 将使用相等操作数 === 为此(谢谢@JimDeville)。有关更多信息,请访问“ Ruby Operators “。这也可以使用@mmdemirbas示例(不带参数)完成,只有这种方法对于这些类型的情况更为干净。

        8
  •  37
  •   DigitalRoss    7 年前

    它叫 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
    

    事实证明,您还可以将任意的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
    
        9
  •  33
  •   the Tin Man    5 年前

    所以,在一个 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    5 年前

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

    按照 case 文档:

    Case语句包含一个可选条件,该条件位于 论点的立场 案例 ,以及零或更多 when 条款。 什么时候 子句来匹配条件(或进行评估) 布尔真值(如果条件为空)获胜,其代码节 被执行。case语句的值是 什么时候 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 ”鲁比说 案例 ;

    可用于 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    5 年前

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

    如果有一长串的 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 Leslie    9 年前

    自从 switch case 始终返回单个对象,我们可以直接打印其结果:

    puts case a
         when 0
            "It's zero"
         when 1
            "It's one"
         end
    
        13
  •  20
  •   Peter Mortensen Leslie    9 年前

    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
    
        14
  •  14
  •   the Tin Man    5 年前

    你可以写 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    8 年前

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

    有很多很好的答案,但我想我会添加一个因素。。如果您试图比较对象(类),请确保您有一个太空船方法(不是玩笑)或了解它们是如何进行比较的

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

        17
  •  8
  •   Community SushiHangover    4 年前

    === 操作员在发动机罩下使用 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? 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/ === "practice zazen today"  # Output: => true
    # is similar to
    "practice zazen today"=~ /zen/
    

    上述两个例子之间唯一相关的区别是,当存在匹配时, 返回true和 =~ 返回一个整数,它是Ruby中的真实值。我们很快就会回到这个话题上。

        18
  •  5
  •   Prabhakar    8 年前
    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
    
        19
  •  4
  •   Peter Mortensen Leslie    9 年前

    我已经开始使用:

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

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

        20
  •  4
  •   the Tin Man    5 年前
    $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

        21
  •  3
  •   the Tin Man    5 年前

    强调逗号很重要( , )在一个 when 条款它充当一个 || 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 x<2'.

    你可能会认为,执行 ,您可以执行以下操作,但它不起作用:

    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
    

    如果 elsif / 其他的 . 然而,无论它是否很少使用,我看不到任何其他方式来附加多个 && 给定对象的表达式 什么时候 条款

        22
  •  3
  •   CPHPython    4 年前

    您的环境中不支持正则表达式吗?例如。 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

        23
  •  1
  •   Vikrant Mayank    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
    
        24
  •  1
  •   the Tin Man    5 年前

    这个 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    3 年前

    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 ,因此您可以使用您喜欢的。

        26
  •  0
  •   AlexSh    3 年前

    我更喜欢使用case+而不是

    number = 10
    
    case number
    when 1...8 then # ...
    when 8...15 then # ...
    when 15.. then # ...
    end
    
        27
  •  0
  •   Moriarty    3 年前

    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