Vraag Hoe schrijf ik een switch-statement in Ruby?


Hoe schrijf ik een switchinstructie in Ruby?


1829
2018-06-04 01:18


oorsprong


antwoorden:


Ruby gebruikt de case uitdrukking in plaats daarvan.

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 vergelijkt het object in de when clausule met het object in de case clausule met behulp van de === operator. Bijvoorbeeld, 1..5 === x, en niet x === 1..5.

Dit maakt verfijning mogelijk when clausules zoals hierboven te zien. Bereiken, klassen en allerlei dingen kunnen worden getest in plaats van alleen gelijkheid.

anders switch verklaringen in veel andere talen, Ruby's case heeft geen doorvalstenen, dus het is niet nodig om elk een einde te maken when met een break. Je kunt ook meerdere overeenkomsten opgeven in een single when clausule zoals when "foo", "bar".


2303
2018-06-04 01:22



case...when gedraagt ​​zich een beetje onverwacht bij het omgaan met klassen. Dit komt door het feit dat het de === operator.

Die operator werkt zoals verwacht met literalen, maar niet met klassen:

1 === 1           # => true
Fixnum === Fixnum # => false

Dit betekent dat als je een a wilt doen case ... when over de klasse van een object, dit zal niet werken:

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

Zal afdrukken "Het is geen reeks".

Gelukkig is dit eenvoudig op te lossen. De === operator is zo gedefinieerd dat deze terugkeert true als je het gebruikt met een klasse en een instantie van die klasse als de tweede operand levert:

Fixnum === 1 # => true

Kortom, de bovenstaande code kan worden opgelost door de .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

Ik heb dit probleem vandaag aangepakt terwijl ik op zoek was naar een antwoord, en dit was de eerste pagina die werd weergegeven, dus ik dacht dat het nuttig zou zijn voor anderen in dezelfde situatie.


396
2018-04-17 15:20



Het is gedaan door geval in Ruby. Zie ook dit artikel op Wikipedia.

geciteerd:

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

Een ander voorbeeld:

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

Op pagina 123 (ik gebruik de Kindle) van The Ruby Programming Lanugage (1e editie, O'Reilly), het zegt het then sleutelwoord na de when clausules kunnen worden vervangen door een nieuwe regel of puntkomma (net als in de if then else syntaxis). (Ruby 1.8 staat ook een dubbele punt toe in plaats van then... Maar deze syntaxis is niet langer toegestaan ​​in Ruby 1.9.)


187
2018-06-04 01:20



    case ... wanneer

Om meer voorbeelden toe te voegen Chuck's antwoord:

Met 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

Zonder 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

Houd er alsjeblieft rekening mee het probleem die kikito waarschuwt.


88
2017-07-05 13:19



Veel programmeertalen, vooral die afgeleid van C, hebben ondersteuning voor de zogenaamde Wissel door. Ik was op zoek naar de beste manier om hetzelfde te doen in Ruby en dacht dat dit nuttig zou kunnen zijn voor anderen:

In C-achtige talen ziet fallthrough er normaal zo uit:

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;
}

In Ruby kan hetzelfde op de volgende manier worden bereikt:

case expression
when 'a', 'b', 'c'
  # Do something for a, b or c
when 'd', 'e'
  # Do something else for d or e
end

Dit is niet strikt equivalent, omdat het niet mogelijk is om te laten 'a' voer een codeblok uit voordat u doorvalt naar 'b' of 'c', maar voor het grootste deel vind ik het vergelijkbaar genoeg om op dezelfde manier nuttig te zijn.


64
2017-12-07 12:11



In Ruby 2.0 kun je ook lambda gebruiken case verklaringen, als volgt:

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

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

U kunt ook eenvoudig uw eigen comparators maken met behulp van een Structuur met een aangepast ===

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

(Voorbeeld overgenomen van "Kan procs worden gebruikt met case-statements in Ruby 2.0?".)

Of, met een complete klas:

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

(Voorbeeld overgenomen van "Hoe een Ruby Case Statement werkt en wat je ermee kunt doen".)


63
2017-08-01 00:04



U kunt reguliere expressies gebruiken, zoals het vinden van een type string:

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's case gebruikt de gelijkheidsoperand === hiervoor (bedankt @JimDeville). Aanvullende informatie is beschikbaar bij "Ruby Operators"Dit kan ook gedaan worden met het @ mmdemirbas voorbeeld (zonder parameter), alleen deze benadering is schoner voor dit soort gevallen.


47
2017-10-16 12:17



Als u graag wilt weten hoe u een OF-voorwaarde in een Ruby-schakelkast gebruikt:

Dus in a case verklaring, a , is het equivalent van || in een if uitspraak.

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

Veel andere dingen die je kunt doen met een Ruby-verklaring


29
2017-07-03 06:46



Het heet case en het werkt zoals je zou verwachten, plus nog veel meer leuke dingen met dank aan === die de tests implementeert.

case 5
  when 5
    puts 'yes'
  else
    puts 'else'
end

Nu voor wat plezier:

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

En het blijkt dat je een willekeurige if / else-ketting (dat wil zeggen, zelfs als de tests geen gemeenschappelijke variabele bevatten) kunt vervangen door case door de initiaal weg te laten case parameter en alleen het schrijven van uitdrukkingen waarbij de eerste overeenkomst is wat u wilt.

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

24
2018-02-05 20:40



Sinds switch case retourneert altijd een enkel object, we kunnen het resultaat direct afdrukken:

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

18
2017-11-05 07:29