javascript: usando una condición en caso de cambio

88

Perdón por esa tonta pregunta. ¿Cómo puedo usar una condición para un caso en el elemento de idioma de cambio de caso de javascript? Como en el ejemplo siguiente, un caso debe coincidir cuando la variable liCountes <= 5 y> 0; sin embargo, mi código no funciona:

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

¡Gracias por cualquier consejo!

haemse
fuente
4
usa declaraciones if en su lugar si quieres hacer eso ..
Naftali alias Neal
3
No debe ignorar a todos los que le dicen que use ifs, porque tienen razón. Esta es una aplicación terrible de switch.
lincolnk
No puedo creer que no se haya proporcionado esta solución. Puede hacer esto, la declaración solo necesita evaluar el valor en la cláusula de cambio. Entonces esto funcionaría: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

Respuestas:

286

Esto funciona:

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

Una versión anterior de esta respuesta consideraba que el paréntesis era el culpable. En verdad, los paréntesis son irrelevantes aquí; lo único que se necesita es que las switch(true){...}expresiones de caso se evalúen como booleanos.

Funciona porque el valor que le damos al interruptor se utiliza como base para comparar. En consecuencia, las expresiones de caso, que también se evalúan como booleanos, determinarán qué caso se ejecuta. También podría dar la vuelta a esto, pasar switch(false){..}y hacer que las expresiones deseadas se evalúen como falso en lugar de verdadero ... pero personalmente prefiero lidiar con condiciones que evalúan la veracidad. Sin embargo, también funciona, por lo que vale la pena tenerlo en cuenta para comprender lo que está haciendo.

Por ejemplo: si liCount es 3, la primera comparación es true === (liCount == 0), lo que significa que el primer caso es falso. Luego, el interruptor pasa al siguiente caso true === (liCount<=5 && liCount>0). Esta expresión se evalúa como verdadera, lo que significa que este caso se ejecuta y termina en break. He añadido paréntesis aquí para que quede más claro, pero son opcionales, según la complejidad de su expresión.

Es bastante simple y una forma ordenada (si encaja con lo que está tratando de hacer) de manejar una larga serie de condiciones, donde tal vez una larga serie ìf() ... else if() ... else if () ...podría introducir mucho ruido visual o fragilidad.

Úselo con precaución, porque es un patrón no estándar, a pesar de ser un código válido.

dmp
fuente
9
Creo que deberías tenerlo switch(true) {, ¿y case liCount == 0:no? De lo contrario, esta comparación es liCount == (liCount <=5 && liCount > 0).
loganfsmyth
33
Sabes, no es porque puedas que debas . Esto es algo que hay que matar con fuego.
JBert
21
Es parte del idioma, por lo tanto, saberlo es mejor que no. Claramente, no sería apropiado para todas las situaciones, pero en un nivel puramente subjetivo, creo que este es un enfoque interesante y más legible / menos frágil que una serie de ifs / elifs en este caso. Lo importante a recordar es que la codificación es una expresión de intención, junto con gusto y práctica. Tener más opciones para expresarse claramente en código nunca es algo malo.
dmp
1
Para mí, esto fue muy útil y una forma muy agradable de organizar mi lógica en la que necesitaba usar un nombre de variable una y otra vez en función de una condición if, pero era un escenario de tipo n + 1, por lo que el hecho de que cambie el caso de declaración sin un descanso se moverá a la siguiente línea a continuación fue críticamente útil.
Joseph Astrahan
2
Incluso nos abrió los ojos para ver cuál habría sido el resultado si la expresión de cambio es falsa como tal switch(false) { }
bello hargbola
24

Que has manera excesivamente complicada eso. Escríbalo con declaraciones if como esta:

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

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

O, si ChaosPandion está tratando de optimizar tanto como sea posible:

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

$('#UploadList').data('jsp').reinitialise();
Eric
fuente
Tenías que ir y uno encima mío. :)
ChaosPandion
Escribimos nuestras publicaciones simultáneamente. No vi el tuyo hasta que ya publiqué. Pareces estar exagerando ahora ...
Eric
Vaya, realmente no pensé en los condicionales demasiado complejos.
ChaosPandion
1
@Chaos: sí, probablemente sea exagerar. También tendría que agregar una verificación nula a setLayoutState: P.
Eric
@Eric: algunos programadores con más vueltas de programación en su haber de las que tengo dicen: "solo porque puedas escribir Javascript sin llaves (y, de hecho, con cuidado, punto y coma) no significa que debas", pero simplemente reescribí algunos if declaraciones como en su ejemplo de todos modos, así que gracias - funciona bien hasta que haya más de una línea para ejecutar después de la condición. Sin embargo, la solución ternaria fue un puente demasiado lejos para mí ...
Dave Everitt
7

Quieres usar declaraciones if:

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

Ver la respuesta de dmp continuación. Eliminaría esta respuesta si pudiera, pero fue aceptada, así que esta es la mejor opción :)

No puedes. Los intérpretes de JS requieren que se compare con la declaración de cambio (por ejemplo, no hay una declaración de "caso cuando"). Si realmente quieres hacer esto, puedes simplemente hacer if(){ .. } else if(){ .. }bloques.

Mark Kahn
fuente
9
Eso es incorrecto. Aquí hay una demostración que muestra cómo funciona: jsfiddle.net/Ender/fr3wL . El estándar ECMAScript establece explícitamente que esto está permitido: docstore.mik.ua/orelly/webprog/jscript/ch06_05.htm#FOOTNOTE-18
Ender
3
@Ender ¿En qué se parece eso a lo que haemse está intentando hacer?
Aistina
@Aistina No lo es. Dado que las condiciones de su caso producen un valor verdadero / falso en lugar de un valor numérico, haemse habría necesitado probar sus casos en busca de un valor de verdad (como lo sugiere la respuesta de danp), en lugar de contrastar con el valor numérico de liCount. Simplemente estaba señalando que la declaración original de Cwolves de que "los intérpretes de JS requieren que las declaraciones de casos sean valores estáticos" era incorrecta. Desde entonces, cwolves ha revisado esta declaración, por lo que mi comentario ya no es relevante.
Ender
Porque esto no responde a la pregunta. No pidió una forma diferente de hacerlo, pidió que la caja del interruptor funcionara como él quería. "Hazlo de otra manera" casi nunca es una respuesta correcta a pesar de que siempre pensamos que lo es. Siempre pensamos que tenemos una mejor manera, pero él no quiere hacerlo así, lo que hace que esta respuesta sea simplemente incorrecta.
Jasmine
@Jasmine - "No puedes, hazlo de otra manera" es perfectamente válido, si es correcto . Mi respuesta es rechazada porque es simplemente incorrecta :) Como señaló @danp, puedes cambiar en contra truey funciona. Pero tiene más de 3 años, así que realmente no me importa.
Mark Kahn
5
switch (true) {
  case condition0:
    ...
    break;
  case condition1:
    ...
    break;
}

funcionará en JavaScript siempre que sus condiciones devuelvan los booleanvalores adecuados , pero no tiene muchas ventajas sobre las else ifdeclaraciones.

Mike Samuel
fuente
¿Funcionará si paso algún número entero 10en la declaración de cambio? en mi caso no funciona, no estoy seguro de cuál es la razón.
Pardeep Jain
10 !== true, entonces no. ¿Existe alguna variable que pueda tener el valor 10? Si x, entonces case x === 10:funcionaría.
Mike Samuel
Pero debería funcionar como otras declaraciones, por ejemplo, si usa el if (10) {..}flujo, debe pasar la Ifcondición, ¿no es así? porque 10 o cualquier número entero excepto 0 se tratará como un valor de verdad y permitirá entrar en la condición. No estoy seguro de qué tiene de malo el cambio de declaración aquí.
Pardeep Jain
1
@PardeepJain, switchsimplemente no funciona como if. ifprueba si la condición es verdadera . switchcomprueba si la expresión después de switches ===( CaseClauseIsSelected paso 4 ) al valor de la expresión posterior case.
Mike Samuel
Oh, así, gracias. Esto era totalmente nuevo para mí. @Mike
Pardeep Jain
4

Ese es un caso en el que debería usar ifcláusulas.

ThiefMaster
fuente
4

Si eso es lo que quiere hacer, sería mejor usar if declaraciones. Por ejemplo:

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
fuente
2

Su código no funciona porque no está haciendo lo que espera que haga. Los bloques de interruptores toman un valor y comparan cada caso con el valor dado, buscando la igualdad. Su valor de comparación es un número entero, pero la mayoría de las expresiones de su caso se resuelven en un valor booleano.

Entonces, por ejemplo, digamos liCount = 2. Tu primer caso no coincidirá, porque 2 != 0. Su segundo caso, (liCount<=5 && liCount>0)evalúa true, pero2 != true , por lo que este caso tampoco coincidirá.

Por este motivo, como han dicho muchos otros, conviene utilizar una serie de if...then...else ifbloques para hacer esto.

Ender
fuente
2

si los valores posibles son números enteros, puede agrupar los casos. De lo contrario, use 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
fuente
0

Tenga en cuenta que no pasamos la puntuación al interruptor, sino que es cierto. El valor que le damos al interruptor se utiliza como base para comparar.

El siguiente ejemplo muestra cómo podemos agregar condiciones en el caso: sin ninguna declaración 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;
}
Pantalón Harshit
fuente
0

Aunque en el ejemplo particular de la pregunta del OP switchno es apropiado, hay un ejemplo en el que el cambio sigue siendo apropiado / beneficioso, pero también se requieren otras expresiones de evaluación. Esto se puede lograr utilizando la cláusula predeterminada para las expresiones:

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
fuente