switch
Rubyでステートメントを書くにはどうすればよいですか?
27 に答える
Rubyは代わりにcase
式を使用します。
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
他の多くの言語のステートメントとは異なり、Rubycase
にはフォールスルーwhen
がないため、それぞれをで終了する必要はありませんbreak
。when
のように、1つの句で複数の一致を指定することもできますwhen "foo", "bar"
。
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
「文字列または数値ではありません」と出力されます。
幸い、これは簡単に解決できます。演算子は、クラスで使用し、そのクラスのインスタンスを2番目のオペランドとして===
指定すると返されるように定義されています。true
Fixnum === 1 # => true
要するに、上記のコードは.class
fromを削除することで修正できます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
今日、答えを探しているときにこの問題にぶつかりました。これが最初に表示されたページだったので、同じ状況で他の人にも役立つと思いました。
これはcase
Rubyで使用して行われます。ウィキペディアの「 Switchステートメント」も参照してください。
引用:
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
KindleのRubyプログラミング言語(第1版、O'Reilly)の123ページあたりでthen
、句に続くキーワードwhen
を改行またはセミコロンに置き換えることができると書かれています(if then else
構文と同じように)。(Ruby 1.8では、の代わりにコロンも使用できthen
ますが、この構文はRuby 1.9では使用できなくなりました。)
ケース...いつ
チャックの答えにさらに例を追加するには:
パラメータ付き:
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
kikitoが警告している「Rubyでswitchステートメントを書く方法」に注意してください。
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
カスタムの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
(「Ruby2.0のcaseステートメントでprocsを使用できますか?」から抜粋した例。)
または、完全なクラスの場合:
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
(「Rubyのcaseステートメントのしくみとそれを使って何ができるか」から抜粋した例。)
多くのプログラミング言語、特にCから派生した言語は、いわゆるSwitchFallthroughをサポートしています。私は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'
文字列のタイプを検索するなど、正規表現を使用できます。
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に感謝)。追加情報は「RubyOperators」で入手できます。これは、@ mmdemirbasの例(パラメーターなし)を使用して実行することもできます。これらのタイプのケースでは、このアプローチのみがよりクリーンです。
それは呼ばれ、あなたが期待するように機能します。さらに、テストを実装するための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
また、初期case
パラメーターを省略し、最初の一致が必要な場所に式を記述するだけで、任意の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
Rubyスイッチの場合にOR条件を使用する方法を知りたがっている場合:
したがって、case
ステートメントでは、aはステートメント内,
と同等です。||
if
case car
when 'Maruti', 'Hyundai'
# Code here
end
Rubyは、case
switchステートメントの記述にforを使用します。
ドキュメントによるとcase
:
Caseステートメントは、引数の位置にあるオプションの条件と
case
、0個以上のwhen
句で構成されます。when
条件に一致する(または条件がnullの場合はブール値の真理に評価される)最初の句が「勝ち」、そのコードスタンザが実行されます。caseステートメントの値は、success句の値when
、またはnil
そのような句がない場合の値です。caseステートメントは
else
句で終了できます。各when
ステートメントには、コンマで区切って複数の候補値を含めることができます。
例:
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のcaseステートメント-高度なテクニック」がRubyを説明しているようにcase
;
範囲で使用できます:
case 5
when (1..10)
puts "case statements match inclusion in a range"
end
## => "case statements match inclusion in a range"
正規表現で使用できます:
case "FOOBAR"
when /BAR$/
puts "they can match regular expressions!"
end
## => "they can match regular expressions!"
Procsと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
場合によっては、メソッドのハッシュを使用することをお勧めします。
sの長いリストがありwhen
、それぞれが(間隔ではなく)比較する具体的な値を持っている場合は、メソッドのハッシュを宣言してから、そのようなハッシュから関連するメソッドを呼び出す方が効果的です。
# 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])
switch case
常に単一のオブジェクトを返すため、その結果を直接出力できます。
puts case a
when 0
"It's zero"
when 1
"It's one"
end
複数値の場合と値のない場合:
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
そしてここでの正規表現ソリューション:
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
case
Rubyでは2つの異なる方法で式を書くことができます。
- 一連の
if
ステートメントに似ています - の横にターゲットを指定する
case
と、各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
あなたはもっと自然な方法でこのようにすることができます、
case expression
when condtion1
function
when condition2
function
else
function
end
すばらしい答えがたくさんありますが、ファクトイドを1つ追加すると思いました。オブジェクト(クラス)を比較する場合は、宇宙船メソッド(ジョークではない)があることを確認するか、それらがどのように比較されているかを理解してください。
「Rubyの同等性とオブジェクトの比較」は、このトピックに関する優れた議論です。
上記の回答の多くで述べられているように、===
演算子はcase
/when
ステートメントの内部で使用されます。
その演算子に関する追加情報は次のとおりです。
大文字小文字の等式演算子:===
===
String、Range、RegexpなどのRubyの組み込みクラスの多くは、「case-equality」、「triple equals」、「threequals」とも呼ばれる独自の演算子の実装を提供します。クラスごとに実装が異なるため、呼び出されたオブジェクトのタイプに応じて動作が異なります。一般に、右側のオブジェクトが左側のオブジェクトに「属している」または「メンバーである」場合は、trueを返します。たとえば、オブジェクトがクラス(またはそのサブクラスの1つ)のインスタンスであるかどうかをテストするために使用できます。
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
です。つまり、左側のオペランドのクラスは、===
呼び出されるメソッドの実装を定義するため、オペランドの位置を交換することはできません。
の正規表現の実装===
右側の文字列が左側の正規表現と一致する場合はtrueを返します。
/zen/ === "practice zazen today" # Output: => true
# is similar to
"practice zazen today"=~ /zen/
上記の2つの例の唯一の関連する違いは、一致する場合、===
trueを=~
返し、整数を返すことです。これは、Rubyの真の値です。すぐにこれに戻ります。
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
私は使い始めました:
a = "secondcase"
var_name = case a
when "firstcase" then "foo"
when "secondcase" then "bar"
end
puts var_name
>> "bar"
場合によってはコードをコンパクトにするのに役立ちます。
$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」を参照してください。
ご使用の環境で正規表現はサポートされていませんか?例:Shopifyスクリプトエディター(2018年4月):
[エラー]:初期化されていない定数RegExp
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?
それでも使用したい||
場合は、この場合or
は望ましいですが、代わりにこれを行うことができます(item.include? 'A') || ...
。このrepl.itでテストできます。
句内のコンマ(,
)を強調することが重要です。when
これは||
ステートメントのif
として機能します。つまり、句の区切り式間のAND比較ではなく、OR比較を行います。次のcaseステートメントを参照してください。when
x = 3
case x
when 3, x < 2 then 'apple'
when 3, x > 2 then 'orange'
end
=> "apple"
x
は2以上ですが、戻り値は"apple"
です。なんで?x
3歳から',`` acts as an
|| , it did not bother to evaluate the expression
x<2'。
ANDを実行すると、以下のようなことができると思うかもしれませんが、機能しません。
case x
when (3 && x < 2) then 'apple'
when (3 && x > 2) then 'orange'
end
=> nil
(3 && x > 2)
がtrueと評価され、RubyがTrue値を取得し、それをと比較するためx
、機能しません。これは、が3===
であるため、trueではありませんx
。
&&
比較するには、/ブロックのように扱う必要がありますcase
。if
else
case
when x == 3 && x < 2 then 'apple'
when x == 3 && x > 2 then 'orange'
end
Rubyプログラミング言語の本の中で、Matzは、この後者の形式は単純な(そしてあまり使用されない)形式であり、//の代替構文にすぎないと述べてif
いelsif
ますelse
。ただし、使用頻度が低いかどうかに関係なく、特定の句に複数の&&
式を付加する方法は他にありません。when
「より小さい」または「より大きい」が必要な場合:
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
ので、好きなものを使用できます。
Ruby 2.6以降では、 Endless Rangesを使用できます。Ruby2.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
case
ステートメント演算子は他のswitch
言語と同じです。
switch...case
これはCの構文です:
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
ドキュメントを参照してください。
複数の条件に対して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
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
ユースケース+よりも
number = 10
case number
when 1...8 then # ...
when 8...15 then # ...
when 15.. then # ...
end