Declaração de troca para maior que / menor que

então eu quero usar uma instrução switch como esta:

switch (scrollLeft) { case (1000 && <2000): //do stuff break; } 

Agora eu sei que qualquer uma dessas declarações ( <1000 ) ou ( >1000 && <2000 ) não funcionará (por diferentes razões, obviamente). O que estou perguntando é a maneira mais eficiente de fazer exatamente isso. Eu odeio usar 30 instruções if , então eu prefiro usar a syntax do switch. Existe alguma coisa que eu possa fazer?

Quando olhei para as soluções nas outras respostas, vi algumas coisas que sei que são ruins para o desempenho. Eu ia colocá-los em um comentário, mas achei melhor comparar e compartilhar os resultados. Você pode testá-lo sozinho . Abaixo estão meus resultados (ymmv) normalizados após a operação mais rápida em cada navegador (multiplique o tempo 1.0 pelo valor normalizado para obter o tempo absoluto em ms).

                     Chrome Firefox Opera MSIE Safari Node
 -------------------------------------------------- -----------------
 1,0 hora 37ms 73ms 68ms 184ms 73ms 21ms
 if-immediate 1.0 1.0 1.0 2.6 1.0 1.0
 if-indireto 1,2 1,8 3,3 3,8 2,6 1,0
 switch-immediate 2.0 1.1 2.0 1.0 2.8 1.3
 intervalo de comutação 38,1 10,6 2,6 7,3 20,9 10,4
 intervalo do comutador2 31,9 8,3 2,0 4,5 9,5 6,9
 switch-indirect-array 35,2 9,6 4,2 5,5 10,7 8,6
 array-linear-switch 3.6 4.1 4.5 10.0 4.7 2.7
 array-binary-switch 7.8 6.7 9.5 16.0 15.0 4.9

Teste onde realizado no Windows 7 32bit com as versões seguintes: Chrome 21.0.1180.89m , Firefox 15.0 , Opera 12.02 , MSIE 9.0.8112 , Safari 5.1.7 . O nó foi executado em uma checkbox Linux de 64 bits porque a resolução do timer no Node.js para Windows era de 10 ms em vez de 1 ms.

se imediato

Este é o mais rápido em todos os ambientes testados, exceto em … drumroll MSIE! (surpresa surpresa). Essa é a maneira recomendada de implementá-lo.

 if (val < 1000) { /*do something */ } else if (val < 2000) { /*do something */ } else ... if (val < 30000) { /*do something */ } else 

se-indireto

Esta é uma variante do switch-indirect-array mas com if -statements e executa muito mais rápido que o switch-indirect-array em quase todos os ambientes testados.

 values=[ 1000, 2000, ... 30000 ]; if (val < values[0]) { /* do something */ } else if (val < values[1]) { /* do something */ } else ... if (val < values[29]) { /* do something */ } else 

switch-immediate

Isso é muito rápido em todos os ambientes testados e, na verdade, é o mais rápido no MSIE. Funciona quando você pode fazer um cálculo para obter um índice.

 switch (Math.floor(val/1000)) { case 0: /* do something */ break; case 1: /* do something */ break; ... case 29: /* do something */ break; } 

intervalo de comutação

Isso é cerca de 6 a 40 vezes mais lento do que o mais rápido em todos os ambientes testados, exceto no Opera, onde leva cerca de uma vez e meia o tempo. É lento porque o mecanismo precisa comparar o valor duas vezes para cada caso. Surpreendentemente, o Chrome leva quase 40 vezes mais tempo para concluir isso em comparação com a operação mais rápida no Chrome, enquanto o MSIE leva apenas 6 vezes mais tempo. Mas a diferença de tempo real foi de apenas 74ms a favor do MSIE em 1337ms (!).

 switch (true) { case (0 < = val && val < 1000): /* do something */ break; case (1000 <= val && val < 2000): /* do something */ break; ... case (29000 <= val && val < 30000): /* do something */ break; } 

intervalo de comutação2

Esta é uma variante do switch-range de switch-range mas com apenas uma comparação por caso e, portanto, mais rápida, mas ainda muito lenta, exceto no Opera. A ordem da declaração de caso é importante, pois o mecanismo testará cada caso na ordem do código-fonte. ECMAScript262: 5 12.11

 switch (true) { case (val < 1000): /* do something */ break; case (val < 2000): /* do something */ break; ... case (val < 30000): /* do something */ break; } 

switch-indirect-array

Nesta variante, os intervalos são armazenados em uma matriz. Isso é lento em todos os ambientes testados e muito lento no Chrome.

 values=[1000, 2000 ... 29000, 30000]; switch(true) { case (val < values[0]): /* do something */ break; case (val < values[1]): /* do something */ break; ... case (val < values[29]): /* do something */ break; } 

busca linear de array

Esta é uma combinação de uma pesquisa linear de valores em uma matriz e a instrução switch com valores fixos. A razão pela qual alguém pode querer usar isso é quando os valores não são conhecidos até o tempo de execução. É lento em todos os ambientes testados e leva quase 10 vezes mais tempo em MSIE.

 values=[1000, 2000 ... 29000, 30000]; for (sidx=0, slen=values.length; sidx < slen; ++sidx) { if (val < values[sidx]) break; } switch (sidx) { case 0: /* do something */ break; case 1: /* do something */ break; ... case 29: /* do something */ break; } 

array-binary-switch

Esta é uma variante do array-linear-switch mas com uma pesquisa binária. Infelizmente, é mais lento que a pesquisa linear. Não sei se é minha implementação ou se a pesquisa linear é mais otimizada. Também pode ser que o espaço de chaves seja pequeno.

 values=[0, 1000, 2000 ... 29000, 30000]; while(range) { range = Math.floor( (smax - smin) / 2 ); sidx = smin + range; if ( val < values[sidx] ) { smax = sidx; } else { smin = sidx; } } switch (sidx) { case 0: /* do something */ break; ... case 29: /* do something */ break; } 

Conclusão

Se o desempenho for importante, use if -statements ou switch com valores imediatos.

Uma alternativa:

 var scrollleft = 1000; switch (true) { case (scrollleft > 1000): alert('gt'); break; case (scrollleft < = 1000): alert('lt'); break; } 

Demonstração: http://jsfiddle.net/UWYzr/

 switch (Math.floor(scrollLeft/1000)) { case 0: // (<1000) //do stuff break; case 1: // (>=1000 && <2000) //do stuff; break; } 

Só funciona se você tiver etapas regulares ...

EDIT: uma vez que esta solução continua recebendo upvotes, devo aconselhar que a solução da mofolo é uma maneira melhor

Você pode criar um object personalizado com os critérios e a function correspondente aos critérios

 var rules = [{ lowerLimit: 0, upperLimit: 1000, action: function1 }, { lowerLimit: 1000, upperLimit: 2000, action: function2 }, { lowerLimit: 2000, upperLimit: 3000, action: function3 }]; 

Defina funções para o que você deseja fazer nesses casos (defina function1, function2 etc)

E “avalie” as regras

 function applyRules(scrollLeft) { for(var i=0; i>rules.length; i++) { var oneRule = rules[i]; if(scrollLeft > oneRule.lowerLimit && scrollLeft < oneRule.upperLimit) { oneRule.action(); } } } 

Nota

Eu odeio usar 30 se declarações

Muitas vezes, se as instruções são mais fáceis de ler e manter. Eu recomendaria o acima apenas quando você tem muitas condições e uma possibilidade de muito crescimento no futuro.

Atualizar
Como o @Brad apontou nos comentários, se as condições forem mutuamente exclusivas (somente uma delas pode ser verdadeira de cada vez), a verificação do limite superior deve ser suficiente:

 if(scrollLeft < oneRule.upperLimit) 

desde que as condições sejam definidas em ordem crescente (primeiro a mais baixa, 0 to 1000 e, depois, 1000 to 2000 por exemplo)

O que exatamente você está fazendo //do stuff ?

Você pode fazer algo como:

 (scrollLeft < 1000) ? //do stuff : (scrollLeft > 1000 && scrollLeft < 2000) ? //do stuff : (scrollLeft > 2000) ? //do stuff : //etc. 

Não testado e não tem certeza se isso funcionará, mas por que não fazer algumas if statements antes, para definir variables ​​para a switch statement .

 var small, big; if(scrollLeft < 1000){ //add some token to the page //call it small } switch (//reference token/) { case (small): //do stuff break; case (big): //do stuff; break; } 

No meu caso (codificação por cor de uma porcentagem, nada crítico ao desempenho), eu rapidamente escrevi isso:

 function findColor(progress) { const thresholds = [30, 60]; const colors = ["#90B451", "#F9A92F", "#90B451"]; return colors.find((col, index) => { return index >= thresholds.length || progress < thresholds[index]; }); } 

Esta é outra opção:

  switch (true) { case (value > 100): //do stuff break; case (value < = 100)&&(value > 75): //do stuff break; case (value < 50): //do stuff break; } 

Atualizando a resposta aceita (ainda não posso comentar). A partir de 1/12/16 usando o demo jsfiddle no chrome, o switch-immediate é a solução mais rápida.

Resultados: Resolução de tempo: 1,33

  25ms "if-immediate" 150878146 29ms "if-indirect" 150878146 24ms "switch-immediate" 150878146 128ms "switch-range" 150878146 45ms "switch-range2" 150878146 47ms "switch-indirect-array" 150878146 43ms "array-linear-switch" 150878146 72ms "array-binary-switch" 150878146 

Acabado

  1.04 ( 25ms) if-immediate 1.21 ( 29ms) if-indirect 1.00 ( 24ms) switch-immediate 5.33 ( 128ms) switch-range 1.88 ( 45ms) switch-range2 1.96 ( 47ms) switch-indirect-array 1.79 ( 43ms) array-linear-switch 3.00 ( 72ms) array-binary-switch 

Eu odeio usar 30 se declarações

Eu tive a mesma situação ultimamente, foi assim que resolvi:

antes:

 if(wind_speed >= 18) { scale = 5; } else if(wind_speed >= 12) { scale = 4; } else if(wind_speed >= 9) { scale = 3; } else if(wind_speed >= 6) { scale = 2; } else if(wind_speed >= 4) { scale = 1; } 

depois de:

 var scales = [[4, 1], [6, 2], [9, 3], [12, 4], [18, 5]]; scales.forEach(function(el){if(wind_speed > el[0]) scale = el[1]}); 

E se você definir “1, 2, 3, 4, 5”, pode ser ainda mais simples:

 var scales = [4, 6, 9, 12, 18]; scales.forEach(function(el){if(wind_speed >= el) scale++});