javascript: utilisation d'une condition dans la casse du commutateur

88

Désolé pour cette question stupide. Comment puis-je utiliser une condition pour un cas dans l'élément de langage javascript switch-case? Comme dans l'exemple ci-dessous, un cas doit correspondre lorsque la variable liCountest <= 5 et> 0; cependant, mon code ne fonctionne pas:

switch (liCount) {
    case 0:
        setLayoutState('start');
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;
    case (liCount<=5 && liCount>0):
        setLayoutState('upload1Row');
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;
    case (liCount<=10 && liCount>5):
        setLayoutState('upload2Rows');
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;
    case (liCount>10):
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;                  
}

Merci pour tout conseil!

hémse
la source
4
utilisez des instructions if à la place si vous voulez faire ça ..
Naftali aka Neal
3
Vous ne devriez pas ignorer tout le monde qui vous dit d'utiliser ifs, car ils ont raison. C'est une terrible application de switch.
lincolnk
Je ne peux pas croire que cette solution n'ait pas été fournie. Vous pouvez le faire, l'instruction doit simplement évaluer la valeur de la clause switch. Donc, cela fonctionnerait:var liCount = 2; switch (liCount) { case 0: console.log(0); break; case (liCount<=5 && liCount>0) && liCount: console.log('liCount<=5 && liCount>0'); break; case (liCount<=10 && liCount>5) && liCount: console.log('liCount<=10 && liCount>5'); break; case (liCount>10) && liCount: console.log(liCount); break; }
Noitidart

Réponses:

286

Cela marche:

switch (true) {
    case liCount == 0:
        setLayoutState('start');
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;
    case liCount<=5 && liCount>0:
        setLayoutState('upload1Row');
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;
    case liCount<=10 && liCount>5:
        setLayoutState('upload2Rows');
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;
    case liCount>10:
        var api = $('#UploadList').data('jsp');
        api.reinitialise();
        break;                  
}

Une version précédente de cette réponse considérait les parenthèses comme le coupable. En vérité, les parenthèses ne sont pas pertinentes ici - la seule chose nécessaire est switch(true){...}que vos expressions de cas soient évaluées en booléens.

Cela fonctionne parce que la valeur que nous attribuons au commutateur est utilisée comme base de comparaison. Par conséquent, les expressions de cas, également évaluées en booléens, détermineront quel cas est exécuté. Pourrait également switch(false){..}inverser la tendance , passer et faire évaluer les expressions souhaitées comme fausses au lieu de vraies ... mais personnellement, préférez traiter des conditions qui évaluent la vérité. Cependant, cela fonctionne aussi, il vaut donc la peine de garder à l'esprit ce qu'il fait.

Par exemple: si liCount vaut 3, la première comparaison est true === (liCount == 0), ce qui signifie que le premier cas est faux. L'interrupteur passe ensuite au cas suivant true === (liCount<=5 && liCount>0). Cette expression prend la valeur true, ce qui signifie que ce cas est exécuté et se termine au break. J'ai ajouté des parenthèses ici pour le rendre plus clair, mais elles sont facultatives, en fonction de la complexité de votre expression.

C'est assez simple et une manière élégante (si cela correspond à ce que vous essayez de faire) de gérer une longue série de conditions, où peut-être une longue série de conditions ìf() ... else if() ... else if () ...pourrait introduire beaucoup de bruit visuel ou de fragilité.

À utiliser avec prudence, car il s'agit d'un modèle non standard, bien qu'il s'agisse d'un code valide.

dmp
la source
9
Je pense que vous en auriez besoin switch(true) {, et case liCount == 0:non? Sinon, cette comparaison est liCount == (liCount <=5 && liCount > 0).
loganfsmyth
33
Vous savez, ce n'est pas parce que vous pouvez que vous devriez . C'est quelque chose qui doit être tué par le feu.
JBert
21
Cela fait partie de la langue - par conséquent, il vaut mieux le connaître. Clairement, cela ne conviendrait pas à toutes les situations, mais sur un plan purement subjectif, je pense que c'est une approche intéressante, et plus lisible / moins fragile qu'une série de ifs / elifs dans ce cas. La chose importante à retenir est que le codage est une expression d'intention, associée au goût et à la pratique. Avoir plus d'options pour vous exprimer clairement dans le code n'est jamais une mauvaise chose.
dmp
1
Pour moi, cela a été très utile et une très bonne façon d'organiser ma logique où je devais utiliser un nom de variable encore et encore en fonction d'une condition if, mais c'était un scénario de type n + 1 donc le fait que l'instruction switch case sans une pause passera à la ligne suivante ci-dessous était extrêmement utile.
Joseph Astrahan
2
Vous avez même ouvert les yeux pour voir quel aurait été le résultat si l'expression du commutateur était fausse comme ça switch(false) { }
bello hargbola
24

Vous avez bien trop compliqué cela. Écrivez-le avec des instructions if à la place comme ceci:

if(liCount == 0)
    setLayoutState('start');
else if(liCount<=5)
    setLayoutState('upload1Row');
else if(liCount<=10)
    setLayoutState('upload2Rows');

$('#UploadList').data('jsp').reinitialise();

Ou, si ChaosPandion essaie d'optimiser autant que possible:

setLayoutState(liCount == 0 ? 'start' :
               liCount <= 5 ? 'upload1Row' :
               liCount <= 10 ? 'upload2Rows' :
               null);

$('#UploadList').data('jsp').reinitialise();
Eric
la source
Tu devais aller et moi. :)
ChaosPandion
Nous avons écrit nos messages simultanément. Je n'ai pas vu le vôtre avant d'avoir déjà posté. Vous semblez en faire trop maintenant ...
Eric
Wow, je n'ai pas vraiment pensé aux conditions trop complexes.
ChaosPandion
1
@Chaos: ouais, c'est probablement en faire trop. Vous devrez également ajouter une vérification nulle à setLayoutState: P.
Eric
@Eric - certains programmeurs avec plus de tours de programmation à leur actif que moi disent: "Ce n'est pas parce que vous pouvez écrire du Javascript sans accolades (et - en fait avec précaution - des points-virgules) que vous devriez", mais je viens de réécrire plusieurs if instructions comme dans votre exemple de toute façon, alors merci - fonctionne bien jusqu'à ce qu'il y ait plus d'une ligne à exécuter après la condition. La solution ternaire était un pont trop loin pour moi, cependant…
Dave Everitt
7

Vous souhaitez utiliser les instructions if:

if (liCount === 0) {
    setLayoutState('start');
} else if (liCount <= 5) {
    setLayoutState('upload1Row');
} else if (liCount <= 10) {
    setLayoutState('upload2Rows');
}
$('#UploadList').data('jsp').reinitialise();  
ChaosPandion
la source
7

Voir la réponse de dmp ci-dessous. Je supprimerais cette réponse si je le pouvais, mais elle a été acceptée, c'est donc la meilleure chose à faire :)

Vous ne pouvez pas. Les interpréteurs JS exigent que vous compariez avec l'instruction switch (par exemple, il n'y a pas d'instruction "case when"). Si vous voulez vraiment faire cela, vous pouvez simplement créer des if(){ .. } else if(){ .. }blocs.

Mark Kahn
la source
9
C'est incorrect. Voici une démo montrant que cela fonctionne: jsfiddle.net/Ender/fr3wL . La norme ECMAScript stipule explicitement que cela est autorisé: docstore.mik.ua/orelly/webprog/jscript/ch06_05.htm#FOOTNOTE-18
Ender
3
@Ender En quoi est-ce la même chose que ce qu'Hemse essaie de faire?
Aistina
@Aistina Ce n'est pas le cas. Puisque ses conditions de cas produisent une valeur vrai / faux plutôt qu'une valeur numérique, haemse aurait eu besoin de tester ses cas pour une valeur de vérité (comme suggéré par la réponse de danp), plutôt que de tester par rapport à la valeur numérique de liCount. Je faisais simplement remarquer que la déclaration originale de cwolves selon laquelle «les interprètes JS exigent que les instructions case soient des valeurs statiques» était incorrecte. cwolves a depuis révisé cette déclaration, donc mon commentaire n'est plus pertinent.
Ender le
Parce que cela ne répond pas à la question. Il n'a pas demandé une autre façon de le faire, il a demandé à faire fonctionner le boîtier de commutation comme il le voulait. "Faites-le d'une autre manière" n'est presque jamais une réponse correcte, même si nous pensons presque toujours que c'est le cas. Nous pensons toujours que nous avons un meilleur moyen, mais ce n'est pas ainsi qu'il veut le faire, ce qui rend cette réponse tout simplement fausse.
Jasmine
@Jasmine - "Vous ne pouvez pas, alors faites-le d'une autre manière" est parfaitement valable, si c'est correct . Ma réponse est votée à la baisse parce que c'est tout simplement faux :) Comme l'a souligné @danp, vous pouvez simplement basculer contre trueet cela fonctionne. Mais il a plus de 3 ans, donc je m'en fiche.
Mark Kahn
5
switch (true) {
  case condition0:
    ...
    break;
  case condition1:
    ...
    break;
}

fonctionnera en JavaScript tant que vos conditions renvoient des booleanvaleurs appropriées , mais cela n'a pas beaucoup d'avantages par rapport aux else ifinstructions.

Mike Samuel
la source
Cela fonctionnera-t-il si je passe un nombre entier 10dans l'instruction switch? dans mon cas ne fonctionne pas je ne sais pas quelle est la raison.
Pardeep Jain
10 !== true, donc non. Y a-t-il une variable qui pourrait avoir la valeur 10? Si x, alors case x === 10:ça marcherait.
Mike Samuel
Mais cela devrait fonctionner comme les autres instructions, par exemple si vous utilisez if (10) {..}flow devrait passer la Ifcondition, n'est-ce pas? car 10 ou tout entier sauf 0 sera traité comme une valeur de vérité et permettra d'entrer dans la condition. Je ne sais pas ce qui ne va pas avec la déclaration de commutation ici.
Pardeep Jain
1
@PardeepJain, switchne fonctionne tout simplement pas comme if. ifteste si la condition est véridique . switchteste si l'expression après le switchest ===( CaseClauseIsSelected étape 4 ) à la valeur de l'expression après case.
Mike Samuel
Ohh comme ça, merci. C'était totalement nouveau pour moi. @Mike
Pardeep Jain
4

C'est un cas où vous devriez utiliser des ifclauses.

ThiefMaster
la source
4

Si c'est ce que vous voulez faire, il serait préférable d'utiliser des ifinstructions. Par exemple:

if(liCount == 0){
    setLayoutState('start');
}
if(liCount<=5 && liCount>0){
    setLayoutState('upload1Row');
}
if(liCount<=10 && liCount>5){
    setLayoutState('upload2Rows');
}             
var api = $('#UploadList').data('jsp');
    api.reinitialise();
Naftali alias Neal
la source
2

Votre code ne fonctionne pas car il ne fait pas ce que vous attendez de lui. Les blocs de commutation prennent une valeur et comparent chaque cas à la valeur donnée, en recherchant l'égalité. Votre valeur de comparaison est un entier, mais la plupart de vos expressions de cas se résolvent en une valeur booléenne.

Alors, par exemple, disons liCount = 2. Votre premier cas ne correspondra pas, car 2 != 0. Votre deuxième cas, (liCount<=5 && liCount>0)évalue à true, mais 2 != true, donc ce cas ne correspondra pas non plus.

Pour cette raison, comme beaucoup d'autres l'ont dit, vous devez utiliser une série de if...then...else ifblocs pour ce faire.

Ender
la source
2

si les valeurs possibles sont des entiers, vous pouvez regrouper les observations. Sinon, utilisez ifs.

var api, tem;

switch(liCount){
    case 0:
    tem= 'start';
    break;
    case 1: case 2: case 3: case 4: case 5:
    tem= 'upload1Row';
    break;
    case 6: case 7: case 8: case 9: case 10:
    tem= 'upload2Rows';
    break;
    default:
    break;
}
if(tem) setLayoutState((tem);
api= $('#UploadList').data('jsp');
api.reinitialise();
Kennebec
la source
0

Notez que nous ne transmettons pas le score au commutateur mais vrai. La valeur que nous attribuons au commutateur est utilisée comme base de comparaison.

L'exemple ci-dessous montre comment nous pouvons ajouter des conditions dans le cas: sans aucune instruction if.

function getGrade(score) {
    let grade;
    // Write your code here
    switch(true) {
        case score >= 0 && score <= 5:
        grade = 'F';
        break;
        case score > 5 && score <= 10:
        grade = 'E';
        break;
        case score > 10 && score <= 15:
        grade = 'D';
        break;
        case score > 15 && score <= 20:
        grade = 'C';
        break;
        case score > 20 && score <= 25:
        grade = 'B';
        break;
        case score > 25 && score <= 30:
        grade = 'A';
        break;
    }

    return grade;
}
Pantalon Harshit
la source
0

Bien que dans l'exemple particulier de la question du PO, switchne soit pas approprié, il y a un exemple où le changement est toujours approprié / bénéfique, mais d'autres expressions d'évaluation sont également nécessaires. Cela peut être réalisé en utilisant la clause par défaut pour les expressions:

switch (foo) {
  case 'bar':
    // do something
    break;
  case 'foo':
    // do something
    break;
  ... // other plain comparison cases
  default:
    if (foo.length > 16) {
      // something specific
    } else if (foo.length < 2) {
      // maybe error
    } else {
      // default action for everything else
    }
}
spikyjt
la source