각 경우에 값 범위와 함께 switch 문을 사용합니까?


92

Java에서 각 케이스에 둘 이상의 값이 포함 된 스위치 문을 작성할 수 있습니까? 예를 들어 (분명히 다음 코드는 작동하지 않습니다) :

switch (num) {
    case 1 .. 5:
        System.out.println("testing case 1 to 5");
        break;
    case 6 .. 10:
        System.out.println("testing case 6 to 10");
        break;
}

Objective C에서 이것이 가능하다고 생각하는데, Java에도 비슷한 것이 있습니까? 아니면 대신 if, else if문을 사용해야 합니까?


이것을 허용하는 일반 C의 확장도 있습니다.
arshajii 2013 년

이 경우 if/else더 나은 해결책이 될 수 있습니다.
Eric Wang

답변:


98

Java에는 그런 종류의 것이 없습니다. 다음을 수행하지 않는 이유는 무엇입니까?

public static boolean isBetween(int x, int lower, int upper) {
  return lower <= x && x <= upper;
}

if (isBetween(num, 1, 5)) {
  System.out.println("testing case 1 to 5");
} else if (isBetween(num, 6, 10)) {
  System.out.println("testing case 6 to 10");
}

1
이것은 훌륭하게 작동하고 간단합니다. 당신이 번호를 선택하려는 경우에도하지 당신이 필요로하는 모든 범위에있는 경우 (isBetween ..., 좋은 일!.
a54studio

1
@missingfaktor 나는 당신의 대답을 약간 비판했습니다 . 그래서, 당신은 아마도 무언가에 답하고 싶을 것입니다. 그래도 +1.
Alexander Malakhov

@MCEmperor, 개인 서식 기본 설정으로 내 대답을 편집하지 마십시오. 그것은 유용한 편집이 아닙니다.
missingfaktor

@missingfaktor 죄송합니다. 그러나 그 편집은 오래 전에 승인되었습니다. 내가 그런 일을 한 적이 있다는 것도 기억하지 못했습니다.
MC Emperor

76

switch명령문을 사용 하여 이러한 종류의 동작에 가장 가까운 것은

switch (num) {
case 1:
case 2:
case 3:
case 4:
case 5:
     System.out.println("1 through 5");
     break;
case 6:
case 7:
case 8:
case 9:
case 10:
     System.out.println("6 through 10");
     break;
}

사용 if진술.


29

다른 대안은 다음과 같이 나누어 수학 연산을 사용하는 것입니다.

switch ((int) num/10) {
    case 1:
        System.out.println("10-19");
        break;
    case 2:
        System.out.println("20-29");
        break;
    case 3:
        System.out.println("30-39");
        break;
    case 4:
        System.out.println("40-49");
        break;
    default:
        break;
}

그러나 보시다시피 범위가 각 경우에 고정 된 경우에만 사용할 수 있습니다.


6
이것은 100으로 나눈 HTTP 상태 코드와 잘 작동
스테판

13

Java에서는 그렇게 할 수 없다고 생각합니다. 가장 좋은 방법은 범위의 마지막 경우에 코드를 넣는 것입니다.

switch (num) {
  case 1: case 2: case 3: case 4: case 5: 
     System.Out.Println("testing case 1 to 5");
     break;
  case 6: case 7: case 8: case 9: case 10:
     System.Out.Println("testing case 6 to 10");
     break;
  default:
     //
}

10
  case 1: case 2: case 3: case 4: case 5: 
         System.out.println("testing case 1 to 5");
         break;
  case 6: case 7: case 8: case 9: case 10:
         System.out.println("testing case 6 to 10");
         break;
  default:
         System.out.println("default"); 

9

나는이 게시물이 오래되었다는 것을 알고 있지만이 답변은 인정받을 가치가 있다고 생각합니다. switch 문을 피할 필요가 없습니다. 이것은 Java에서 수행 할 수 있지만 case가 아닌 switch 문을 통해 수행 할 수 있습니다. 삼항 연산자를 사용합니다.

public class Solution {

    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int num = Integer.parseInt(sc.nextLine());

        switch ((1 <= num && num <= 5 ) ? 0 :
                (6 <= num && num <= 10) ? 1 : 2) {

            case 0:
                System.out.println("I'm between one and five inclusive.");
                break;
            case 1:
                System.out.println("I'm between 6 and 10 inclusive.");
                break;
            case 2:
                System.out.println("I'm not between one and five or 6 and 10 inclusive.");
                break;
        }
    }
}

1
좋은 해결책! 자바 7 당신의 경우는 더 예를 들어 자기 문서화, 그래서 높은 당신은 또한 문자열에 전환 할 수있는 switch ((1 <= num && num <= 5 ) ? "1 .. 5" : ...다음과 case "1 .. 5":.
Daniel Widdis

@DanielWiddis : 일관성을 보장하기 위해 문자열 대신 열거 형을 사용하는 것이 좋습니다.
nmatt

@nmatt 일반적으로 동의합니다. 나는 "1 .. 5"스타일 구문의 사용을 허용하려고했다.
Daniel Widdis

2
@DanielWiddis : 확실히 좋은 일입니다. 열거 형 상수의 이름을 FROM_1_TO_5와 같이 지정하겠습니다. 일반적으로 범위에는 특정 의미가 있으며이 경우 범위의 의미에 따라 열거 형 상수의 이름을 지정할 수 있습니다.
nmatt

1
두 옵션 중 하나가 0, 1 또는 2보다 낫다는 데 동의 할 수 있다고 생각합니다.
Daniel Widdis

6

또는 의도 한대로 솔로 케이스를 사용하고 기본 케이스를 사용하여 범위 지침을 다음과 같이 지정할 수 있습니다.

switch(n) {
    case 1 : System.out.println("case 1"); break;
    case 4 : System.out.println("case 4"); break;
    case 99 : System.out.println("case 99"); break;
    default :
        if (n >= 10 && n <= 15)
            System.out.println("10-15 range"); 
        else if (n >= 100 && n <= 200)
            System.out.println("100-200 range");
        else
            System.out.println("Your default case");
        break;   
}

이것은 내가 항상하는 일이지만, 예를 들어 다음과 같이 경우 사이에 주석을 추가합니다. // 10-15 기본값 아래 참조
Perdi Estaquel

5

스위치를 사용해야하는 경우 이것을 시도하십시오.

public static int range(int num){ 
    if ( 10 < num && num < 20)
        return 1;
    if ( 20 <= num && num < 30)
        return 2;
    return 3;
}

public static final int TEN_TWENTY = 1;
public static final int TWENTY_THIRTY = 2;

public static void main(String[]args){
    int a = 110;
    switch (range(a)){
        case TEN_TWENTY: 
            System.out.println("10-20"); 
            break;
        case TWENTY_THIRTY: 
            System.out.println("20-30"); 
            break;
        default: break;
    }
}

당신도 설명해 주시겠습니까 ..?
user1140237

함수 범위는 입력 인수에 따라 일부 값을 반환하므로 여기서 "값 범위"감지를 스위치 케이스 절과 함께 수행 할 수 있습니다.
zl9394

이것은 내 유스 케이스에서 작동합니다. 2 개의 int 변수가 있고 2 개의 변수가 (10-20), (20-30), ....과 같은 동일한 범위에 있는지 확인하고 싶습니다. 이렇게
Sameer Kazi

magic int 값 대신 enum을 사용하는 것이 좋습니다.
nmatt

4

아니 당신은 할 수 없습니다. 당신이 할 수있는 최선은

case 1:
case 2:
case 3:
case 4:
case 5: 
  System.Out.Println("testing case 1 to 5");
break;

3

switch 문에 의해 허용되는 fall throughcase 메커니즘을 사용하여 동일한 문 에서 여러 조건을 그룹화 할 수 있습니다. 이는 Java 자습서 에서 언급 되고 섹션 §14.11에 완전히 지정되어 있습니다 . 스위치 문Java 언어 사양 .

다음 코드 스 니펫은 자습서의 예제에서 가져온 것으로, 매월 일 수를 계산합니다 (1 개월부터 12 개월까지 번호 지정).

switch (month) {
    case 1: case 3: case 5:
    case 7: case 8: case 10:
    case 12:
        numDays = 31;
        break;
    case 4: case 6:
    case 9: case 11:
        numDays = 30;
        break;
    case 2:
        if (((year % 4 == 0) && 
             !(year % 100 == 0))
             || (year % 400 == 0))
            numDays = 29;
        else
            numDays = 28;
        break;
    default:
        System.out.println("Invalid month.");
        break;
}

보시다시피 단일 case명령문 에서 값 범위를 다루는 유일한 대안은 가능한 값을 하나씩 하나씩 나열하는 것입니다. 추가 예로서 다음은 질문에서 의사 코드를 구현하는 방법입니다.

switch(num) {
    case 1: case 2: case 3: case 4: case 5:
        System.out.println("testing case 1 to 5");
        break;
    case 6: case 7: case 8: case 9: case 10:
        System.out.println("testing case 6 to 10");
        break;
}

3

enum범위를 나타내는 데 사용할 수 있습니다.

public static enum IntRange {
  ONE_TO_FIVE, SIX_TO_TEN;
  public boolean isInRange(int v) {
    switch (this) {
    case ONE_TO_FIVE:
      return (v >= 1 && v <= 5);
    case SIX_TO_TEN:
      return (v >= 6 && v <= 10);
    }
    return false;
  }

  public static IntRange getValue(int v) {
    if (v >= 1 && v <= 5) {
      return ONE_TO_FIVE;
    } else if (v >= 6 && v <= 10) {
      return SIX_TO_TEN;
    }
    return null;
  }
}

3

Java 12부터 지원됩니다. 체크 아웃 . JEP 354를 . 여기서 "범위"가능성은 없지만 유용 할 수 있습니다.

switch (day) {
    case MONDAY, FRIDAY, SUNDAY -> System.out.println(6);//number of letters
    case TUESDAY                -> System.out.println(7);
    case THURSDAY, SATURDAY     -> System.out.println(8);
    case WEDNESDAY              -> System.out.println(9);
}

int에서도 구현할 수 있어야합니다. switch 문은 완전해야합니다 ( default키워드 사용 또는 case 문에서 가능한 모든 값 사용).


3

아름답고 미니멀 한 방법이 있습니다.

(num > 1 && num < 5) ? first_case_method() 
                     : System.out.println("testing case 1 to 5")
                     : (num > 5 && num < 7)  ? System.out.println("testing case 5 to 7") 
                     : (num > 7 && num < 8)  ? System.out.println("testing case 7 to 8") 
                     : (num > 8 && num < 9)  ? System.out.println("testing case 8 to 9") 
                     : ... 
                     : System.out.println("default");

이것을 설명 할 수 있습니까 ?? -나는 'mini ifs'를 얻지 만 그 idk가 아닙니다.
Kamin Pallaghy

@Tunaki 이것은 if..elseif삼항 연산자 ( condition ? statementIfTrue : statementIfFalse) 를 캐스케이드로 사용 하는 대안 입니다.
Williem

2

@missingfaktor의 대답은 실제로 정확하지만 약간 복잡합니다. 코드는 (적어도 연속 간격의 경우) 더 장황 할 수 있으며 long, float, Integer 등에 대한 오버로드 / 캐스트 및 / 또는 매개 변수화가 필요합니다.

if (num < 1)
    System.Out.Println("invalid case: " + num); // you should verify that anyway
else if (num <= 5)
    System.Out.Println("1 to 5");
else if (num <= 10)
    System.Out.Println("6 to 10");
else if (num <= 42)
    System.Out.Println("11 to 42");
else    
    System.Out.Println("43 to +infinity");

3
응답이 늦어서 죄송합니다. 최근에 SO 응답을 따라갈 수 없습니다. 당신의 비판에 하나씩 답변 해 드리겠습니다. 1. 코드는 좀 더 장황합니다. 그렇습니다. 또한 중복 계산도 수행합니다. 그러나 그 IMO는이 경우 명확성을 돕습니다. 코드에서 사다리를 통과 할 때 이전 사례를 기억해야합니다.
missingfaktor 2014-06-20

2
과부하 및 캐스트 요구에 관해서는 유효한 비판 IMO가 아닙니다. Java에는 숫자 유형을 추상화하는 현명한 방법이 없다는 것은이 접근 방식보다 Java의 한계에 대해 말합니다. Num이 점을 더 잘 이해하고 싶다면 Haskell의 유형 클래스 를 탐색 할 수 있습니다 .
missingfaktor 2014-06-20

@missingfaktor 1. 그게 취향의 문제라고 생각합니다. 연속 간격을 다룰 때 개인적으로 ifs를 낮은 하위 범위에서 점차적으로 쏟아져 나오는 것처럼 생각하고 싶습니다 . 또한 중복 계산은 전혀 문제가되지 않지만 중복 비교는 약간 걱정 스럽습니다. 예를 들어 일부 편집 후 인접한 비교를 동기화하지 않는 것이 더 간단 해집니다 if (isBetween(x, 1, 4)) {...} else if (isBetween(x, 6, 10)). 어쨌든 큰 문제는 아닙니다.
Alexander Malakhov 2014-06-23

2. 동의 함-Java의 제한 사항이지만 이것이 우리가 작업해야하는 것이며 원본 코드는 다양한 유형에 대해 복제됩니다. 이 특별한 경우에는 Number 클래스 를 사용하여 문제를 완화 할 수 있지만 Haskell의 접근 방식이 더 낫습니다 (진짜 Haskell을 배우지 못했지만 C ++의 "Concepts Light"와 비슷합니다. 또한 Real, 아니라고 생각합니다 Num).
Alexander Malakhov 2014 년

2

NavigableMap와 같은 구현을 사용하십시오 TreeMap.

/* Setup */
NavigableMap<Integer, Optional<String>> messages = new TreeMap<>();
messages.put(Integer.MIN_VALUE, Optional.empty());
messages.put(1, Optional.of("testing case 1 to 5"));
messages.put(6, Optional.of("testing case 6 to 10"));
messages.put(11, Optional.empty());

/* Use */
messages.floorEntry(3).getValue().ifPresent(System.out::println);

훌륭한 솔루션! if (messages.floorEntry(value)!=null) 정수 값을 사용하는 경우 null을 확인하는 것을 잊지 마십시오
Ch Vas

1
@ChVas 여기서 맵이 설정된 방식은 floorEntry()반환되지 않습니다 null( Integer.MIN_VALUE키 삽입은 이를 방지하기위한 것입니다). 그러나 값 유형에 관계없이 유효한 범위를 벗어난 키를 처리하는 방법을 결정해야합니다.
erickson

0

0..100 범위의 입력 번호

int n1 = 75; // input value
String res; int n=0; 
int[] a ={0,20,35,55,70,85,101};

for(; n1>=a[n]; n++);
switch(6-n+1) {
  case 1: res="A"; break;
  case 2: res="B"; break;
  case 3: res="C"; break;
  case 4: res="D"; break;
  case 5: res="E"; break;
  default:res="F";
}
System.out.println(res);

0

이러한 유형의 동작은 Java에서 지원되지 않습니다. 그러나이를 필요로하는 대규모 프로젝트가있는 경우 프로젝트에서 Groovy 코드를 혼합하는 것을 고려하십시오. Groovy 코드는 바이트 코드로 컴파일되며 JVM과 함께 실행할 수 있습니다. 내가 일하는 회사는 Groovy를 사용하여 서비스 클래스를 작성하고 Java를 사용하여 다른 모든 것을 작성합니다.

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