それぞれの場合に値の範囲を含むswitchステートメントを使用していますか?


91

Javaでは、各ケースに複数の値が含まれるswitch文を書くことは可能ですか?たとえば、(ただし、次のコードは機能しませんが):

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でも同様のことはありますか?またはifelse if代わりに、ステートメントを使用する必要がありますか?


これを可能にするプレーンCの拡張機能もあります。
arshajii 2013

回答:


97

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 2017

@missingfaktorすみません。しかし、その編集はずっと前に承認されました。私はそれをしたことを覚えていませんでした。
MC皇帝

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:
     //
}

9

私はこの投稿が古いことを知っていますが、この答えはある程度の評価に値すると思います。switchステートメントを回避する必要はありません。これはJavaで実行できますが、ケースではなく、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
素敵な解決策!Javaの7以降で、また、あなたの場合は、例えば、さらに自己文書化されているように文字列に切り替えて、可能性がありswitch ((1 <= num && num <= 5 ) ? "1 .. 5" : ...、その後とcase "1 .. 5":
ダニエルウィディス

@DanielWiddis:一貫性を確保するために、文字列の代わりに列挙型を使用することをお勧めします。
nmatt

@nmatt一般的に同意します。「1 .. 5」スタイルの構文の使用を許可しようとしました。
ダニエルウィディス

1
@DanielWiddis:確かに良いことです。列挙型定数にはFROM_1_TO_5のような名前を付けます。通常、範囲には特定の意味があり、その場合、列挙定数は範囲の意味に従って名前を付けることができます。
nmatt

どちらのオプションも0、1、または2より優れていることに同意できると思います
ダニエルウィディス

9
  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"); 

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

関数rangeは入力引数に応じて一部の値を返すため、ここで「値の範囲」の検出をswitch case句と組み合わせて行うことができます。
zl9394

これは私のユースケースで機能します。2つのint変数があり、2つの変数が(10-20)、(20-30)、...のように同じ範囲にあることを確認したいのですが、このように
Sameer Kazi

magic int値の代わりに列挙型を使用することをお勧めします。
nmatt

5

または、意図的にソロのケースを使用し、デフォルトのケースを使用して範囲の指示を次のように指定することもできます。

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

4

いいえ、それはできません。あなたができる最善はそれです

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

3

switchステートメントで許可されるフォールスルーcaseのメカニズムを使用して、同じステートメント内のいくつかの条件をグループ化することが可能です。これは、Javaチュートリアルで言及されており、§14.11で完全に指定されていますswitch文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;
  }
}

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年

2
オーバーロードとキャストを要求することに関しては、それは正当な批判IMOではありません。Javaが数値型を抽象化する賢明な方法を持たないということは、このアプローチよりも、Javaの制限について語っています。Numこの点をよりよく理解したい場合は、Haskellの型クラスを調べてみてください。
missingfaktor 2014年

@missingfaktor 1.好みの問題だと思います。連続的な間隔を扱うとき、私は個人的には、ifsが次第に下位の範囲をこぼしているかのように考えるのが好きです。さらに、冗長な計算はまったく問題ではありませんが、冗長な比較は少し心配ですif (isBetween(x, 1, 4)) {...} else if (isBetween(x, 6, 10))。とにかく、大したことではありません。
Alexander Malakhov 14年

2.同意-Javaの制限。ただし、これは私たちが作業する必要があるものであり、元のコードはさまざまなタイプで複製されます。この特定のケースで問題が使用することによって緩和することができる番号 Haskellのアプローチは優れているものの、クラスを(実際にはHaskellを学ぶために来なかったが、それはC ++の「光の概念を」似ているん。また、私はあなたが意味するものと信じてReal、ではありませんNum)。
Alexander Malakhov 14年

2

美しくてシンプルな方法です

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

これを説明できますか?-私は「ミニifs」を取得しますが、そのidk以外です。
Kamin Pallaghy 16

@Tunakiこれはif..elseif、三項演算子(condition ? statementIfTrue : statementIfFalse)をカスケードで使用する代替方法です。
Williem

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()は決して戻りませんnullInteger.MIN_VALUEキーの挿入はそれを防ぐことを目的としています)。ただし、値のタイプに関係なく、有効範囲外のキーの処理方法を決定する必要があります。
エリクソン2016年

2

Java 12以降でサポートされています。JEP354を確認してください。ここには「範囲」の可能性はありませんが、どちらも役立ちます。

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ステートメントで可能なすべての値を使用します)。


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.