when - ruby switch case




Wie schreibe ich eine switch-Anweisung in Ruby? (14)

Fall ... wann

Um noch mehr Beispiele zu Chucks Antwort hinzuzufügen:

Mit 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

Ohne 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

Bitte beachten Sie das Problem, dass Kikito warnt.

Wie schreibe ich eine Switch-Anweisung in Ruby?


Abhängig von Ihrem Fall könnten Sie einen Hash der Methoden bevorzugen.

Wenn es eine lange Liste von wann gibt und jede von ihnen einen konkreten Wert hat, mit dem verglichen werden kann (kein Intervall), ist es effektiver, einen Hash der Methoden zu deklarieren und dann die relevante Methode aus dem Hash aufzurufen.

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

Es heißt case und es funktioniert wie man es erwarten würde, plus viel mehr Spaß mit freundlicher Genehmigung von === die die Tests implementiert.

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

Jetzt für etwas Spaß:

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

Und es stellt sich heraus, dass Sie auch eine beliebige if / else-Kette (das heißt, selbst wenn die Tests keine gemeinsame Variable beinhalten) durch case ersetzen können, indem Sie den initialen case Parameter weglassen und nur Ausdrücke schreiben, bei denen die erste Übereinstimmung ist wollen.

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

Es wird in Ruby von case . Siehe auch diesen Artikel auf Wikipedia .

Zitiert:

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

Ein anderes Beispiel:

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

Auf Seite 123 (ich benutze Kindle) von The Ruby Programming Lanugage (1. Ausgabe, O'Reilly) sagt es, dass das then Schlüsselwort nach den when Klauseln mit einem Newline oder Semikolon ersetzt werden kann (genau wie in der if then else Syntax) ). (Ruby 1.8 erlaubt auch einen Doppelpunkt anstelle von ... Aber diese Syntax ist in Ruby 1.9 nicht mehr erlaubt.)


In Ruby 2.0 können Sie auch lambdas in case Anweisungen wie folgt verwenden:

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

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

Sie können auch Ihre eigenen Vergleicher einfach mit einem Struct mit einem benutzerdefinierten ===

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

(Beispiel aus " Kann Procs mit Case-Anweisungen in Ruby 2.0 verwendet werden? ".)

Oder mit einer kompletten Klasse:

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

(Beispiel aus " Wie funktioniert eine Ruby-Case-Anweisung und was kann man damit machen? ")


In Ruby können Sie Case-Ausdrücke auf zwei verschiedene Arten schreiben.

  1. Ähnlich einer Reihe von "if" -Anweisungen
  2. Geben Sie ein Ziel neben der Groß- / Kleinschreibung an und jede "when" -Klausel wird mit dem Ziel verglichen.

1. Weg

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

2. Weg

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

Mehrwertiger Fall mit und ohne Wert

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

Und eine reguläre Ausdruckslösung hier:

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

Ruby verwendet den case zum Schreiben von Switch-Anweisungen.

Wie in den Ruby Docs :

Case-Anweisungen bestehen aus einer optionalen Bedingung, die in der Position eines Arguments für case , und null oder mehr when Klauseln. Die erste when Klausel, die mit der Bedingung übereinstimmt (oder mit boolescher Wahrheit ausgewertet wird, wenn die Bedingung null ist), "gewinnt" und ihre Codezeilengruppe wird ausgeführt. Der Wert der case-Anweisung ist der Wert der erfolgreichen when Klausel oder nil wenn keine solche Klausel vorhanden ist.

Eine case-Anweisung kann mit einer else Klausel enden. Jeder, when eine Anweisung mehrere durch Kommas getrennte Kandidatenwerte enthalten kann.

Beispiel:

case x
when 1,2,3
  puts "1, 2, or 3"
when 10
  puts "10"
else
  puts "Some other number"
end

Kürzere Version:

case x
when 1,2,3 then puts "1, 2, or 3"
when 10 then puts "10"
else puts "Some other number"
end

Und wie dieser Blog von Honeybadger Ruby Case beschreibt;

Kann mit Ranges :

case 5
when (1..10)
  puts "case statements match inclusion in a range"
end

## => "case statements match inclusion in a range"

Kann mit Regex :

case "FOOBAR"
when /BAR$/
  puts "they can match regular expressions!"
end

## => "they can match regular expressions!"

Kann mit Procs und Lambdas verwendet werden :

case 40
when -> (n) { n.to_s == "40" }
  puts "lambdas!"
end

## => "lambdas"

Kann auch mit eigenen Match-Klassen verwendet werden:

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

Sie können reguläre Ausdrücke verwenden, um z. B. einen Zeichenfolgetyp zu finden:

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

Rubys case verwendet den Gleichheitsoperanden === dafür (danke @JimDeville). Weitere Informationen finden Sie unter " Ruby Operators ". Dies kann auch mit @mmdemirbas Beispiel (ohne Parameter) geschehen, nur diese Vorgehensweise ist für diese Fälle sauberer.


Viele Programmiersprachen, insbesondere solche, die von C abgeleitet sind, unterstützen den sogenannten Switch Fallthrough . Ich war auf der Suche nach dem besten Weg, das gleiche in Ruby zu tun und dachte, dass es für andere nützlich sein könnte:

In C-ähnlichen Sprachen sieht der Fallout typischerweise so aus:

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 kann dasselbe auf folgende Weise erreicht werden:

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

Dies ist nicht unbedingt gleichwertig, weil es nicht möglich ist, einen Code auszuführen, bevor er durch 'b' oder 'c' fällt, aber ich finde es meistens ähnlich genug, um auf die gleiche Weise nützlich zu sein.



Wie in vielen der obigen Antworten angegeben, wird der Operator === unter der Haube von case / when-Anweisungen verwendet.

Hier finden Sie einige zusätzliche Informationen zu diesem Operator.

Fallgleichheitsoperator: ===

Viele der in Ruby integrierten Klassen wie String, Range und Regexp bieten ihre eigenen Implementierungen des Operators ===, die auch als Fallgleichheit, Dreifachgleichheit oder Dreigleichheit bezeichnet werden. Da es in jeder Klasse anders implementiert ist, verhält es sich abhängig vom Objekttyp, für den es aufgerufen wurde, unterschiedlich. Im Allgemeinen wird der Wert true zurückgegeben, wenn das Objekt auf der rechten Seite "gehört" oder "ein Mitglied" des Objekts auf der linken Seite ist. Zum Beispiel kann es verwendet werden, um zu testen, ob ein Objekt eine Instanz einer Klasse (oder einer ihrer Unterklassen) ist.

String === "zen"  # Output: => true
Range === (1..2)   # Output: => true
Array === [1,2,3]   # Output: => true
Integer === 2   # Output: => true

Das gleiche Ergebnis kann mit anderen Methoden erreicht werden, die für den Job am besten geeignet sind, wie is_a? und instance_of ?.

Bereich Implementierung von ===

Wenn der Operator === für ein Bereichsobjekt aufgerufen wird, wird True zurückgegeben, wenn der Wert auf der rechten Seite in den Bereich auf der linken Seite fällt.

(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

Denken Sie daran, dass der Operator === die Methode === des linken Objekts aufruft. Also (1..4) === 3 ist äquivalent zu (1..4). === 3. Mit anderen Worten definiert die Klasse des linken Operanden, welche Implementierung der ===-Methode sein wird aufgerufen, so dass die Operandenpositionen nicht austauschbar sind.

Regexp Implementierung von ===

Gibt true zurück, wenn die Zeichenfolge auf der rechten Seite mit dem regulären Ausdruck auf der linken Seite übereinstimmt. / zen / === "praktiziere Zazen heute" # Ausgabe: => Wahr # ist ähnlich wie "praktiziere Zazen heute" = ~ / zen /

Der einzige relevante Unterschied zwischen den beiden obigen Beispielen ist, dass, wenn eine Übereinstimmung vorliegt, === Wahr liefert und = ~ eine ganze Zahl zurückgibt, was ein Truthy-Wert in Ruby ist. Wir werden bald darauf zurückkommen.


Ruby verwendet stattdessen den case Ausdruck .

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 vergleicht das Objekt in der when Klausel mit dem Objekt in der case Klausel mit dem Operator === . Zum Beispiel, 1..5 === x , und nicht x === 1..5 .

Dies ermöglicht ausgefeilte when Klauseln, wie oben zu sehen. Bereiche, Klassen und alle möglichen Dinge können getestet werden und nicht nur die Gleichheit.

Im Gegensatz zu switch Anweisungen in vielen anderen Sprachen hat Rubys case keinen fall-through , so dass es nicht notwendig ist, jeden when einer break zu beenden. Sie können auch mehrere Übereinstimmungen in einer einzelnen when Klausel angeben, z. B. when "foo", "bar" .








conditional