Vous utilisez l'instruction switch avec une plage de valeurs dans chaque cas?

92

En Java, est-il possible d'écrire une instruction switch où chaque cas contient plus d'une valeur? Par exemple (bien que clairement le code suivant ne fonctionnera pas):

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

Je pense que cela peut être fait en Objective C, y a-t-il une chose similaire en Java? Ou devrais - je utiliser simplement if, des else ifdéclarations à la place?

davidx1
la source
Il y a même des extensions en C clair qui permettent cela.
arshajii
Dans ce cas, c'est peut if/else- être une meilleure solution.
Eric Wang le

Réponses:

98

Java n'a rien de ce genre. Pourquoi ne pas faire ce qui suit?

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");
}
manquant
la source
1
Cela fonctionne très bien et est simple. Aussi, si vous voulez sélectionner des numéros qui ne sont pas dans la plage, tout ce dont vous avez besoin est si (! IsB Between ..., good job.
a54studio
1
@missingfaktor J'ai un peu critiqué votre réponse. Donc, vous voudrez probablement répondre quelque chose. +1 cependant.
Alexander Malakhov
@MCEmperor, veuillez ne pas modifier ma réponse avec vos préférences de formatage personnelles. Ce n'est pas une modification utile.
missingfaktor
@missingfaktor Désolé. Mais cette modification a été approuvée il y a longtemps; Je ne me souvenais même pas que j'avais déjà fait ça.
MC Emperor
76

Le plus proche de ce type de comportement avec des switchdéclarations est

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

Utilisez des ifdéclarations.

Jeffrey
la source
29

une autre alternative consiste à utiliser l'opération mathématique en la divisant, par exemple:

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

Mais, comme vous pouvez le voir, cela ne peut être utilisé que lorsque la plage est fixe dans chaque cas.

Hayi Nukman
la source
6
Cela fonctionne bien avec les codes de statut http divisés par 100.
Stefan
13

Je ne pense pas que vous puissiez faire cela en Java. Le mieux est de simplement mettre le code dans le dernier cas de la plage.

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:
     //
}
blitzen
la source
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"); 
Jitendra
la source
9

Je sais que cet article est ancien mais je pense que cette réponse mérite une certaine reconnaissance. Il n'est pas nécessaire d'éviter l'instruction switch. Cela peut être fait en java mais via l'instruction switch, pas les cas. Il s'agit d'utiliser des opérateurs ternaires.

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;
        }
    }
}
DarkHark
la source
1
Belle solution! Avec Java 7 et supérieur, vous pouvez également activer une chaîne afin que vos cas soient encore plus auto-documentés, par exemple, switch ((1 <= num && num <= 5 ) ? "1 .. 5" : ...et ensuite case "1 .. 5":.
Daniel Widdis
@DanielWiddis: Je suggérerais d'utiliser une énumération au lieu de chaînes, pour assurer la cohérence.
nmatt
@nmatt En général d'accord. J'essayais d'autoriser l'utilisation de la syntaxe de style "1 .. 5".
Daniel Widdis
2
@DanielWiddis: Certainement une bonne chose; Je nommerais les constantes d'énumération quelque chose comme FROM_1_TO_5. Habituellement, les plages ont une certaine signification, et dans ce cas, les constantes d'énumération peuvent être nommées en fonction de la signification de la plage.
nmatt
1
Je pense que nous pouvons convenir que l'une ou l'autre option est meilleure que 0, 1 ou 2.
Daniel Widdis
6

Ou vous pouvez utiliser vos cas solo comme prévu et utiliser votre cas par défaut pour spécifier les instructions de plage comme:

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;   
}
Xalamadrax
la source
C'est ce que je fais toujours, mais aussi ajouter un commentaire entre les cas, par exemple: // 10 - 15 voir ci-dessous par défaut
Perdi Estaquel
5

Essayez ceci si vous devez utiliser switch.

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;
    }
}
zl9394
la source
pouvez-vous s'il vous plaît donner une explication aussi ..?
user1140237
La plage de fonctions renvoie une valeur en fonction de l'argument d'entrée, de sorte que la détection de «plage de valeurs» peut être effectuée ici, couplée à la clause switch case.
zl9394
Cela fonctionne pour mon cas d'utilisation, j'ai 2 variables int et je veux vérifier que 2 variables sont dans la même plage comme (10-20), (20-30), .... comme ça
Sameer Kazi
Je suggérerais d'utiliser une énumération au lieu de valeurs magiques int.
nmatt
4

Non, vous ne pouvez pas faire ça. Le mieux que vous puissiez faire est que

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

Il est possible de regrouper plusieurs conditions dans une même caseinstruction en utilisant le mécanisme de chute autorisé par les instructions switch, il est mentionné dans le tutoriel Java et entièrement spécifié dans la section §14.11. La déclaration switch de la spécification du langage Java .

L'extrait de code suivant est tiré d'un exemple du didacticiel, il calcule le nombre de jours de chaque mois (numérotés du mois 1 au mois 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;
}

Comme vous pouvez le voir, pour couvrir une plage de valeurs dans une seule caseinstruction, la seule alternative est de lister chacune des valeurs possibles individuellement, l'une après l'autre. Comme exemple supplémentaire, voici comment implémenter le pseudocode dans la question:

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;
}
Óscar López
la source
3

Vous pouvez utiliser un enumpour représenter vos plages,

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;
  }
}
Elliott Frisch
la source
3

Il est pris en charge à partir de Java 12. Consultez JEP 354 . Pas de possibilité de «gamme» ici, mais peut être utile non plus.

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

Vous devriez également pouvoir l'implémenter sur ints. Notez que votre instruction switch doit être exhaustive (en utilisant un defaultmot clé ou en utilisant toutes les valeurs possibles dans les instructions case).

A_Arnold
la source
3

Voici une manière magnifique et minimaliste d'aller

(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");
Williem
la source
Pouvez-vous expliquer cela ?? - J'obtiens les «mini ifs» mais à part ça idk.
Kamin Pallaghy
@Tunaki c'est une if..elseifalternative utilisant en cascade l'opérateur ternaire ( condition ? statementIfTrue : statementIfFalse).
Williem
2

La réponse de @missingfaktor est en effet correcte mais un peu trop compliquée. Le code est plus détaillé (au moins pour des intervalles continus) qu'il pourrait l'être, et nécessite des surcharges / casts et / ou un paramétrage pour long, float, Integer, etc.

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");
Alexandre Malakhov
la source
3
Désolé pour la réponse tardive, je ne suis pas en mesure de suivre les réponses SO ces derniers temps. Je répondrai à votre critique une par une. 1. Le code est un peu plus détaillé, oui, et il effectue également des calculs redondants. Mais cette OMI contribue à la clarté dans ce cas. Dans votre code, il faut se souvenir des cas précédents en passant par l'échelle.
missingfaktor
2
Quant à exiger des surcharges et des lancers, ce n'est pas une critique valable de l'OMI. Le fait que Java n'ait aucun moyen sensé d'abstraire des types numériques en dit long sur les limitations de Java, plus que sur cette approche. Vous voudrez peut-être explorer la Numclasse de type de Haskell si vous souhaitez mieux comprendre ce point.
missingfaktor
@missingfaktor 1. Je suppose que c'est une question de goût. Lorsqu'il s'agit d'intervalles continus, j'aime personnellement penser aux ifs comme si je débordais progressivement de la sous-plage inférieure. En outre, un calcul redondant n'est pas un problème du tout, mais la comparaison redondante est un peu inquiétant: il devient plus simple de faire des comparaisons adjacentes désynchronisés, par exemple après un certain edit: if (isBetween(x, 1, 4)) {...} else if (isBetween(x, 6, 10)). Quoi qu'il en soit, ce n'est pas grave.
Alexander Malakhov
2. D'accord - limitation de Java, mais c'est ce avec quoi nous devons travailler et votre code original sera dupliqué pour différents types. Dans ce cas particulier, un problème peut être atténué en utilisant la classe Number , bien que l'approche de Haskell soit meilleure (jamais vraiment appris Haskell, mais cela ressemble à "Concepts Light" de C ++. De plus, je crois que vous vouliez dire Realnon Num).
Alexander Malakhov
2

Utilisez une NavigableMapimplémentation, comme 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);
Erickson
la source
Excellente solution! n'oubliez pas de vérifier la valeur nulle en utilisant if (messages.floorEntry(value)!=null) si vous utilisez une valeur entière
Ch Vas
1
@ChVas La façon dont la carte est configurée ici, floorEntry()ne reviendra jamais null(l'insertion de la Integer.MIN_VALUEclé vise à empêcher cela). Mais, quel que soit votre type de valeur, vous devez décider comment gérer les clés en dehors de la plage valide.
erickson
0

Pour numéro d'entrée dans la plage 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);
Zemiak
la source
0

Ce type de comportement n'est pas pris en charge en Java. Cependant, si vous avez un grand projet qui en a besoin, envisagez de mélanger du code Groovy dans votre projet. Le code Groovy est compilé en code octet et peut être exécuté avec JVM. L'entreprise pour laquelle je travaille utilise Groovy pour écrire des classes de service et Java pour tout écrire.

isoplayer
la source