Ruby에서 switch 문을 작성하는 방법


답변:


2669

루비는 대신 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

루비는 절을 사용하여 절의 when객체와 절의 객체를 비교합니다 . 예를 들어, 및 아닙니다 .case===1..5 === xx === 1..5

이를 통해 when위에서 본 것처럼 정교한 절이 가능합니다 . 범위, 클래스 및 모든 종류의 것들을 평등이 아닌 테스트 할 수 있습니다.

달리 switch다른 많은 언어 문, 루비는 case없는 추락을 통해 각각의 종료 할 필요가 없습니다, when와 함께 break. when같은 단일 절 에 여러 개의 일치 항목을 지정할 수도 있습니다 when "foo", "bar".


12
전달 된 인수에 대해 정규 표현식을 수행 할 수도 있습니다. / thisisregex / 다음 줄 에 "이것은 찾은 일치 번호입니다 1 # {$ 1}"끝
Automatico

8
또한 주목할 가치가 있는 것과 같은 줄에 whenand return문을 넣어 코드를 줄일 수 있습니다 .when "foo" then "bar"
Alexander-Reinstate Monica

9
중요 : 달리 switch다른 많은 언어 진술은 루비는 case없는 추락을 통해 각각의 종료 할 필요가 없습니다, when와 함께 break.
janniks

3
너무 많은 투표로 키워드에 대한 언급조차 없습니다 then. 다른 답변도 참조하십시오.
클린트 Pachl

442

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다음 을 제거하여 수정할 수 있습니다 .

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

나는 오늘 대답을 찾는 동안이 문제에 부딪 쳤으며 이것이 처음으로 나타나는 페이지이므로 동일한 상황에서 다른 사람들에게 유용 할 것이라고 생각했습니다.


obj = 'hello'; 케이스 obj; 때 '안녕하세요'다음 박았 "그것의 안녕하세요"끝
Sugumar Venkatesan

.class에 참여하는 것은, 덕분에주의하는 것이 재미있다. 물론 이것은 전적으로 적절한 행동입니다 (그러나 그것이 인쇄 될 것이라고 생각하는 일반적인 실수가 어떻게 보일지 알 수 있습니다 It is a string) ... 당신은 객체 자체가 아닌 임의의 객체 클래스 를 테스트하고 있습니다. 예를 들어 case 'hello'.class when String then "String!" when Class then "Class!" else "Something else" end결과는 다음 "Class!"과 같습니다 1.class. {}.class, 등에서 동일하게 작동합니다 . Dropping .class, 이러한 다양한 값을 얻 "String!"거나 얻습니다 "Something else".
lindes

219

caseRuby에서 사용 합니다. Wikipedia의 " 스위치 설명 " 도 참조하십시오 .

인용 :

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 Programming Language (1st Edition, O'Reilly)의 123 페이지 부근 then에서 when절 다음의 키워드를 구문에서와 같이 줄 바꿈 또는 세미콜론으로 바꿀 수 있다고 말합니다 if then else. (Ruby 1.8은 대신에 콜론을 then허용하지만이 구문은 Ruby 1.9에서 더 이상 허용되지 않습니다.)


38
when (-1.0/0.0)..-1 then "Epic fail"
Andrew Grimm

이것은 사례 스위치의 결과를 기반으로 변수를 정의하기 때문에 내가 사용한 대답입니다. type = #{score}각 줄을 말하지 않고 단순히 내가 한 일을 복사 할 수 있습니다. 훨씬 더 우아한 나는 또한 가능하다면 원 라이너를 훨씬 더 좋아한다
onebree

나는 이것이 답의 본질과 관련이 없다는 것을 알고 있지만 4는 또한 완벽한 제곱입니다.
Nick Moore

109

사건 ... 때

척의 답변 에 더 많은 예제를 추가하려면 :

매개 변수로 :

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

의 유의하십시오 " 어떻게 루비에서 switch 문을 작성하는 kikito에 대해 경고 것을".


감사합니다. 한 줄에 여러 옵션이있는 데 도움이되었습니다. 나는 사용하려고 노력했다or
sixty4bit

73

많은 프로그래밍 언어, 특히 C에서 파생 된 프로그래밍 언어는 소위 스위치 폴 스루를 지원합니다 . 루비에서 똑같이하는 가장 좋은 방법을 찾고 있었고 다른 사람들에게 유용 할 것이라고 생각했습니다.

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

루비에서도 다음과 같은 방법으로 달성 할 수 있습니다.

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' 하지는 않지만 대부분 동일한 방식으로 유용 할 정도로 유사하다는 것을 알았습니다.


72

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

( " Ruby 2.0에서 procs를 case 문과 함께 사용할 수 있습니까?" "

또는 완전한 수업으로 :

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

( " 루비 사례 설명의 작동 방식과 할 수있는 작업 "에서 발췌 한 예 )


52

문자열 유형 찾기와 같은 정규식을 사용할 수 있습니다.

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 덕분에). 추가 정보는 " 루비 연산자 " 에서 확인할 수 있습니다 . 이것은 매개 변수없이 @mmdemirbas 예제를 사용하여 수행 할 수 있으며 이러한 유형의 경우에는이 방법 만 더 명확합니다.



33

그것은 호출 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

23

루비는 case스위치 문을 작성 하기 위해를 사용합니다 .

당으로 case문서 :

case 문은에 대한 인수 위치에있는 선택적 조건 case과 0 개 이상의 when절로 구성됩니다. when조건과 일치하는 (또는 조건이 null 인 경우 부울 진리로 평가 되는) 첫 번째 절이 "승리"되고 해당 코드 스탠자가 실행됩니다. case 문의 값은 성공한 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의 사례 기술-고급 기술 "은 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

22

경우에 따라 해시 방법을 사용하는 것이 좋습니다.

whens 의 긴 목록이 있고 각각에 (구간이 아닌) 비교할 구체적인 값이있는 경우 메소드의 해시를 선언 한 다음 해시에서 관련 메소드를 호출하는 것이 더 효과적입니다.

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

21

switch case항상 단일 객체를 반환 하므로 결과를 직접 인쇄 할 수 있습니다.

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

20

가치없는 경우와 가치없는 경우 :

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

2
왜 안돼? case some_string, when /\d/, (stuff), when /[a-zA-Z]/, (stuff), end( ,개행을 의미하는 곳 )
Doorknob

2
아, 그리고 첫 번째 부분은 이미이 답변 에서 다뤄 졌으며 많은 답변이 이미 정규식에 대해 언급했습니다. 솔직히이 답변은 새로운 것을 추가하지 않으며 삭제하기 위해 투표하고 투표하고 있습니다.
Doorknob

@DoorknobofSnow 스위치 케이스에서 Regex 솔루션과 쉼표로 구분 된 값을 사용할 수 있음을 보여줍니다. 솔루션이 왜 그렇게 많은 고통을 주는지 잘 모르겠습니다.
123

그래서 그들이 "F", 적법한 등급을 받았다면, 그 결점은 당신의 코드에 케이스가없는 것입니까?
Mike Graf

나는 이것의 유머를 좋아하며, 문자열을 사례에 일치시킬 수 있음을 보여줍니다.
emery

13

caseRuby에서 두 가지 방법으로 표현식을 작성할 수 있습니다 .

  1. 일련의 if진술 과 유사
  2. 옆에 대상을 지정하면 casewhen절이 대상과 비교됩니다.
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

코드가 질문에 대답 할 수 있지만 코드의 기능과 초기 문제를 해결하는 방법 에 대한 간단한 설명을 추가해야합니다 .
user1438038

앞으로이 팁을 고려할 것입니다.
ysk

10

보다 자연스러운 방식으로이 작업을 수행 할 수 있습니다.

case expression
when condtion1
   function
when condition2
   function
else
   function
end

9

많은 훌륭한 답변이 있지만 사실을 하나 더 추가 할 것이라고 생각했습니다. 객체 (클래스)를 비교하려는 경우 우주선 방법 (농담이 아님)이 있는지 또는 비교 방법을 이해해야합니다.

" 루비 평등과 객체 비교 "는이 주제에 대한 좋은 토론입니다.


7
참고로, "우주선 (space-ship)"방법은 <=>비교가 각각보다 작거나, 같거나, 더 크거나 또는 비교할 수 없는지 여부에 따라 -1, 0, 1 또는 nil을 반환하는 데 사용됩니다. Ruby의 Comparable 모듈 설명서에 설명되어 있습니다.
Tin Man

7

위의 많은 답변에서 언급했듯이 ===연산자는 case/when 문 .

해당 연산자에 대한 추가 정보는 다음과 같습니다.

대소 문자 평등 연산자 : ===

String, Range 및 Regexp와 같은 많은 Ruby 내장 클래스 ===는 "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?and 와 같이 해당 작업에 가장 적합한 다른 방법으로도 동일한 결과를 얻을 수 있습니다 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/

위의 두 예제의 유일한 차이점은 일치하는 항목이 있으면 ===true를 =~반환하고 정수를 반환하며 이는 Ruby의 값입니다. 곧 다시 연락 드리겠습니다.


5
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

1
왜 이것이 바람직한 솔루션인지 설명하고 작동 방식을 설명하면 도움이됩니다. 우리는 단지 코드를 제공하는 것이 아니라 교육하기를 원합니다.
Tin Man

3
$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, not "을 참조하십시오.


1

나는 사용하기 시작했다 :

a = "secondcase"

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

puts var_name
>> "bar"

경우에 따라 압축 코드가 도움이됩니다.


1
이와 같은 코드는 일반적으로 명령문이 Hash아닌을 사용하여 수행해야 case합니다.
Tom Lord

스위치가 커지면 해시를 사용하는 것이 더 빠릅니다.
Tin Man

1

환경에서 정규 표현식을 지원하지 않습니까? 예 : Shopify Script Editor (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?. 당신이 ruby-nazi 인 경우 , 이것을 (item.include? 'A') || ...대신 사용 했다고 상상해보십시오 . 반복 테스트.


1

,에서 쉼표 ( ) 를 강조하는 것이 중요합니다 when. 명령문 ||의 역할을합니다 . 즉, 절의 구분 된 표현식 간의 AND 비교가 아니라 OR 비교 를 수행합니다 . 다음 사례 진술을 참조하십시오.ifwhen

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

x2 이상이지만 반환 값은 "apple"입니다. 왜? 때문에 x3 년 이후였다 ',`` acts as an|| , it did not bother to evaluate the expressionx <2 '.

AND 를 수행하려면 다음과 같이 할 수 있지만 작동하지 않습니다.

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

이 때문에 작동하지 않습니다 (3 && x > 2)참으로 평가를하고, 루비 진정한 가치를 받아와 비교 x=== 있기 때문에, 진실하지 않은, x3입니다.

&&비교 를하려면 / 블록 case처럼 취급해야합니다 :ifelse

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

루비 프로그래밍 언어 책에서 마츠는이 후자의 형태에 대한 대안 구문에 불과하다 간단한 (그리고 자주 사용) 형태로 말한다 if/ elsif/ else. 그러나 자주 사용되는지 여부에 관계없이 &&주어진 when절 에 여러 표현식 을 첨부하는 다른 방법은 없습니다 .


이것은 나에게 좋은 코딩 스타일처럼 보이지 않습니다. 드문 대체 구문을 사용하면 불필요하게 난독 화됩니다. 왜 보통을 사용하지 if...elsif않습니까? 사례 진술과 조건을 혼합하려고하는 것 같습니다. 왜? 예를 들어 when 블록 안에 조건부를 넣으십시오 . when 3; ( x < 2 ) ? 'apple' : 'orange'
sondra.kinsey 2014 년

0

여러 조건에 대한 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

1
작동하지 않습니다. 루비 키워드 (예. case, when, end) 대소 문자를 구분와 같이 대문자 수 없습니다.
sondra.kinsey 2014 년

NoMethodError (undefined method main : Object의 경우 CASE '). @ sondra.kinsey가 말했듯이 대문자를 사용할 수 없습니다. 루비는 그것이 상수라고 생각할 것입니다.
Tin Man

0

case문 연산자처럼 switch다른 언어입니다.

이것은 switch...caseC 의 구문입니다 .

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

이것은 case...whenRuby 의 문법입니다 :

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설명서를 참조하십시오 .

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.