javascript: usando uma condição em caso de troca

88

Desculpe por essa pergunta idiota. Como posso usar uma condição para um caso no elemento de linguagem javascript switch-case? Como no exemplo abaixo, um caso deve corresponder quando a variável liCounté <= 5 e> 0; no entanto, meu código não 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;                  
}

Obrigado por qualquer conselho!

haemse
fonte
4
use instruções if se quiser fazer isso ..
Naftali, também conhecido como Neal,
3
Você não deve ignorar todos que lhe dizem para usar ifs, porque eles estão certos. Esta é uma aplicação terrível de switch.
Lincolnk
Não acredito que esta solução não foi fornecida. Você pode fazer isso, a instrução só precisa avaliar o valor na cláusula switch. Portanto, isso funcionaria: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

Respostas:

286

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

Uma versão anterior dessa resposta considerava os parênteses os culpados. Na verdade, os parênteses são irrelevantes aqui - a única coisa necessária é switch(true){...}e para que suas expressões de caso sejam avaliadas como booleanos.

Funciona porque o valor que atribuímos ao switch é usado como base para comparação. Consequentemente, as expressões de caso, também avaliando para booleanos, determinarão qual caso será executado. Também poderia inverter isso e passar switch(false){..}e ter as expressões desejadas avaliadas como falsas em vez de verdadeiras ... mas pessoalmente prefere lidar com condições que avaliam a veracidade. No entanto, também funciona, portanto, vale a pena ter em mente para entender o que está fazendo.

Ex: se liCount for 3, a primeira comparação é true === (liCount == 0), o que significa que o primeiro caso é falso. O switch então passa para o próximo caso true === (liCount<=5 && liCount>0). Esta expressão é avaliada como verdadeira, o que significa que este caso é executado e termina no break. Eu adicionei parênteses aqui para deixar isso mais claro, mas eles são opcionais, dependendo da complexidade de sua expressão.

É muito simples e uma maneira legal (se se encaixa com o que você está tentando fazer) de lidar com uma longa série de condições, onde talvez uma longa série de ìf() ... else if() ... else if () ...pode introduzir muito ruído visual ou fragilidade.

Use com cautela, pois é um padrão fora do padrão, apesar de ser um código válido.

dmp
fonte
9
Eu acho que você precisa ter switch(true) {, case liCount == 0:certo? Caso contrário, esta comparação é liCount == (liCount <=5 && liCount > 0).
loganfsmyth
33
Você sabe, não é porque você pode que deveria . Isso é algo que precisa ser morto com fogo.
JBert
21
Faz parte da linguagem - conseqüentemente, saber disso é melhor do que não saber. Claramente, não seria apropriado para todas as situações, mas em um nível puramente subjetivo, acho que esta é uma abordagem interessante, e mais legível / menos frágil do que uma série de ifs / elifs neste caso. O importante a lembrar é que a codificação é uma expressão da intenção, associada ao gosto e à prática. Ter mais opções para se expressar claramente em código nunca é uma coisa ruim.
dmp
1
Para mim, isso foi muito útil e uma maneira muito boa de organizar minha lógica onde eu precisava usar um nome de variável repetidamente com base em uma condição if, mas era um cenário do tipo n + 1, então o fato de que o caso da instrução switch sem uma pausa para passar para a próxima linha abaixo foi extremamente útil.
Joseph Astrahan
2
Você até abriu nossos olhos para ver qual teria sido o resultado se a expressão do switch fosse falsa assim switch(false) { }
bello hargbola
24

Você maneira demasiado complicada que isso. Escreva-o com instruções if em vez disso:

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

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

Ou, se ChaosPandion está tentando otimizar o máximo possível:

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

$('#UploadList').data('jsp').reinitialise();
Eric
fonte
Você teve que ir e um acima de mim. :)
ChaosPandion
Escrevemos nossos posts simultaneamente. Não vi o seu até já ter postado. Você parece estar exagerando agora ...
Eric
Uau, eu realmente não pensei sobre as condicionais excessivamente complexas.
ChaosPandion
1
@Chaos: sim, provavelmente é um exagero. Você também teria que adicionar uma verificação de nulo a setLayoutState: P.
Eric
@Eric - alguns programadores com mais voltas de programação em seu currículo do que eu dizem: "só porque você pode escrever Javascript sem chaves (e - na verdade com cuidado - ponto-e-vírgula) não significa que você deveria", Mas eu apenas reescrevi alguns múltiplos instruções if como em seu exemplo de qualquer maneira, então obrigado - funciona bem até que haja mais de uma linha para executar após a condição. A solução ternária era uma ponte longe demais para mim, no entanto ...
Dave Everitt
7

Você deseja usar instruções if:

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

Veja a resposta do dmp abaixo. Eu excluiria esta resposta se pudesse, mas foi aceita, então esta é a próxima melhor coisa :)

Você não pode. Os intérpretes JS exigem que você compare com a instrução switch (por exemplo, não há instrução "caso quando"). Se você realmente quiser fazer isso, basta fazer if(){ .. } else if(){ .. }blocos.

Mark Kahn
fonte
9
Isso está incorreto. Aqui está uma demonstração mostrando que ele está funcionando: jsfiddle.net/Ender/fr3wL . O padrão ECMAScript declara explicitamente que isso é permitido: docstore.mik.ua/orelly/webprog/jscript/ch06_05.htm#FOOTNOTE-18
Ender
3
@Ender Por que isso é igual ao que Haemse está tentando fazer?
Aistina
@Aistina Não é. Visto que suas condições de caso produzem um valor verdadeiro / falso ao invés de um valor numérico, haemse teria que testar seus casos para um valor verdadeiro (como sugerido pela resposta de danp), em vez de testar contra o valor numérico de liCount. Eu estava apenas apontando que a afirmação original de cwolves de que "JS os intérpretes exigem que as instruções de caso sejam valores estáticos" estava incorreta. cwolves já revisou esta declaração, então meu comentário não é mais relevante.
Fim de
Porque isso não responde à pergunta. Ele não pediu uma maneira diferente de fazer isso, ele pediu para fazer a caixa de troca funcionar como ele deseja. "Faça de outra maneira" quase nunca é uma resposta correta, apesar de estarmos sempre pensando que é. Sempre pensamos que temos uma maneira melhor, mas não é assim que ele quer, tornando esta resposta completamente errada.
Jasmine
@Jasmine - "Você não pode, então faça de outra maneira" é perfeitamente válido, se estiver correto . Minha resposta está sendo rejeitada porque está errada :) Como @danp apontou, você pode simplesmente mudar contra truee funciona. Mas tem mais de 3 anos, então eu realmente não me importo.
Mark Kahn
5
switch (true) {
  case condition0:
    ...
    break;
  case condition1:
    ...
    break;
}

funcionará em JavaScript, desde que suas condições retornem booleanvalores adequados , mas não tem muitas vantagens sobre as else ifinstruções.

Mike Samuel
fonte
Vai funcionar se eu passar algum número inteiro 10na instrução switch? no meu caso não funciona não sei qual é o motivo.
Pardeep Jain
10 !== true, então não. Existe alguma variável que possa ter o valor 10? Se x, então case x === 10:funcionaria.
Mike Samuel
Mas deve funcionar como outras instruções, por exemplo, se você usar if (10) {..}flow deve passar na Ifcondição, não é? porque 10 ou qualquer número inteiro exceto 0 será tratado como um valor verdadeiro e permitirá entrar na condição. Não tenho certeza do que há de errado com a instrução switch aqui.
Pardeep Jain
1
@PardeepJain, switchsimplesmente não funciona assim if. iftesta se a condição é verdadeira . switchtesta se a expressão após switché ===( CaseClauseIsSelected etapa 4 ) ao valor da expressão após case.
Mike Samuel
Ohh assim, obrigado. Isso era totalmente novo para mim. @Mike
Pardeep Jain
4

É um caso em que você deve usar ifcláusulas.

ThiefMaster
fonte
4

Se é isso que você deseja fazer, seria melhor usar ifinstruções. Por exemplo:

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 também conhecido como Neal
fonte
2

Seu código não funciona porque não está fazendo o que você espera que faça. Os blocos de alternância recebem um valor e comparam cada caso com o valor fornecido, procurando igualdade. Seu valor de comparação é um número inteiro, mas a maioria das expressões de caso resolve para um valor booleano.

Então, por exemplo, digamos liCount = 2. Seu primeiro caso não corresponderá, porque 2 != 0. Seu segundo caso, (liCount<=5 && liCount>0)avalia para true, mas2 != true , portanto, este caso também não corresponderá.

Por esse motivo, como muitos outros já disseram, você deve usar uma série de if...then...else ifblocos para fazer isso.

Ender
fonte
2

se os valores possíveis forem inteiros, você pode agrupar casos. Caso contrário, 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
fonte
0

Observe que não passamos pontuação para o switch, mas é verdade. O valor que atribuímos ao switch é usado como base para comparação.

O exemplo abaixo mostra como podemos adicionar condições no caso: sem nenhuma instrução 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;
}
Calça Harshit
fonte
0

Embora no exemplo particular da pergunta do OP switchnão seja apropriado, há um exemplo em que a troca ainda é apropriada / benéfica, mas outras expressões de avaliação também são necessárias. Isso pode ser feito usando a cláusula padrão para as expressões:

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
fonte