Sentencia Switch for greater-than / less-than
Así que quiero usar una instrucción switch como esta:
switch (scrollLeft) {
case (<1000):
//do stuff
break;
case (>1000 && <2000):
//do stuff
break;
}
Ahora sé que cualquiera de esas declaraciones (<1000
) o (>1000 && <2000
) no funcionará (por diferentes razones, obviamente). Lo que estoy pidiendo es la forma más eficiente de hacer precisamente eso. Odio usar sentencias 30 if
, así que prefiero usar la sintaxis switch. ¿Hay algo que pueda hacer?
10 answers
Cuando miré las soluciones en las otras respuestas vi algunas cosas que sé que son malas para el rendimiento. Iba a ponerlos en un comentario, pero pensé que era mejor compararlo y compartir los resultados. Puedes probarlo tú mismo . A continuación se muestran mis resultados (ymmv) normalizados después de la operación más rápida en cada navegador (multiplique el tiempo 1.0 con el valor normalizado para obtener el tiempo absoluto en ms).
Chrome Firefox Opera MSIE Safari Node ------------------------------------------------------------------- 1.0 time 37ms 73ms 68ms 184ms 73ms 21ms if-immediate 1.0 1.0 1.0 2.6 1.0 1.0 if-indirect 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 switch-range 38.1 10.6 2.6 7.3 20.9 10.4 switch-range2 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
Prueba donde se realizó en Windows 7 32bit con el siguientes versiones: Chrome 21.0.1180.89 m, Firefox 15.0, la Ópera 12.02, MSIE 9.0.8112, Safari 5.1.7. Node se ejecutó en una caja Linux de 64 bits debido a la resolución del temporizador en el nodo.js para Windows era 10ms en lugar de 1ms.
If-inmediata
Este es el más rápido en todos los entornos probados, excepto en ... redoble de tambores MSIE! (sorpresa, sorpresa). Esta es la forma recomendada de implementar se.
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
If-indirecto
Esta es una variante de switch-indirect-array
pero if
-instrucciones y realiza mucho más rápido que switch-indirect-array
en casi todos los entornos probados.
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-inmediato
Esto es bastante rápido en todos los entornos probados, y en realidad el más rápido en MSIE. Funciona cuando se puede hacer un cálculo para obtener un índice.
switch (Math.floor(val/1000)) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
Rango de conmutación
Esto es aproximadamente de 6 a 40 veces más lento que el más rápido en todos los entornos probados excepto para la ópera, donde se tarda aproximadamente una vez y media más. Es lento porque el motor tiene que comparar el valor dos veces para cada caso. Sorprendentemente, se necesita Chrome casi 40 veces más tiempo para completar esto en comparación con la operación más rápida en Chrome, mientras que MSIE solo toma 6 veces más tiempo. Pero la diferencia de tiempo real fue de solo 74 ms a favor de MSIE en 1337 ms (!).
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;
}
Switch-rango2
Esta es una variante de switch-range
pero con solo una comparación por caso y por lo tanto más rápido, pero aún muy lento, excepto en la Ópera. El orden de la instrucción case es importante ya que el motor probará cada caso en el orden del código fuente ECMAScript262:5 12.11
switch (true) {
case (val < 1000): /* do something */ break;
case (val < 2000): /* do something */ break;
...
case (val < 30000): /* do something */ break;
}
Conmutador-matriz indirecta
En esta variante los rangos se almacenan en una matriz. Esto es lento en todos los entornos probados y muy lento en 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;
}
Array-linear-search
Esta es una combinación de una búsqueda lineal de valores en una matriz, y el interruptor declaración con valores fijos. La razón por la que uno podría querer usar esto es cuando el los valores no se conocen hasta el tiempo de ejecución. Es lento en todos los entornos probados, y toma casi 10 veces más tiempo en 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 es una variante de array-linear-switch
, pero con una búsqueda binaria.
Desafortunadamente es más lento que la búsqueda lineal. No se si es mi implementación o si la búsqueda lineal está más optimizada. También podría ser que el keyspace es pequeño.
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;
}
Conclusión
Si el rendimiento es importante, use if
-sentencias o switch
con valores inmediatos.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-07 05:21:30
Una alternativa:
var scrollleft = 1000;
switch (true)
{
case (scrollleft > 1000):
alert('gt');
break;
case (scrollleft <= 1000):
alert('lt');
break;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-15 13:33:21
switch (Math.floor(scrollLeft/1000)) {
case 0: // (<1000)
//do stuff
break;
case 1: // (>=1000 && <2000)
//do stuff;
break;
}
Solo funciona si tiene pasos regulares...
EDITAR: dado que esta solución sigue recibiendo votos positivos, debo aconsejar que la solución de mofolo es una manera mejor
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-05 11:35:02
Puede crear un objeto personalizado con los criterios y la función correspondientes a los criterios
var rules = [{ lowerLimit: 0, upperLimit: 1000, action: function1 },
{ lowerLimit: 1000, upperLimit: 2000, action: function2 },
{ lowerLimit: 2000, upperLimit: 3000, action: function3 }];
Define funciones para lo que quieres hacer en estos casos (define function1, function2, etc.)
Y "evaluar" las reglas
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
Odio usar 30 if declaraciones
Muchas veces si las declaraciones son más fáciles de leer y mantener. Recomendaría lo anterior solo cuando tiene muchas condiciones y una posibilidad de lote de crecimiento en el futuro.
Actualizar
Como @Brad señaló en los comentarios, si las condiciones son mutuamente excluyentes (solo una de ellas puede ser verdadera a la vez), verificar el límite superior debería ser suficiente:
if(scrollLeft < oneRule.upperLimit)
siempre que las condiciones se definan en orden ascendente (primero la más baja, 0 to 1000
, y luego 1000 to 2000
por ejemplo)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-13 07:55:45
¿Qué estás haciendo exactamente en //do stuff
?
Usted puede ser capaz de hacer algo como:
(scrollLeft < 1000) ? //do stuff
: (scrollLeft > 1000 && scrollLeft < 2000) ? //do stuff
: (scrollLeft > 2000) ? //do stuff
: //etc.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-12 14:47:30
No probado e inseguro si esto funcionará, pero por qué no hacer unos cuantos if statements
antes, para establecer variables para el 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;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-07-12 14:47:56
En mi caso (color-coding a percentage, nothing performance-critical), rápidamente escribí esto:
function findColor(progress) {
const thresholds = [30, 60];
const colors = ["#90B451", "#F9A92F", "#90B451"];
return colors.find((col, index) => {
return index >= thresholds.length || progress < thresholds[index];
});
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-28 09:09:21
Esta es otra opción:
switch (true) {
case (value > 100):
//do stuff
break;
case (value <= 100)&&(value > 75):
//do stuff
break;
case (value < 50):
//do stuff
break;
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-07-19 13:18:34
Actualizando la respuesta aceptada (aún no se puede comentar). A partir del 1/12/16 utilizando la demo jsfiddle en chrome, switch-immediate es la solución más rápida.
Resultados: Resolución de tiempo: 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
Terminado
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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-12 21:36:57
Odio usar 30 if declaraciones
Tuve la misma situación últimamente, así es como lo resolví:
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;
}
Después 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]});
Y si se establece "1, 2, 3, 4, 5" entonces puede ser aún más simple:
var scales = [4, 6, 9, 12, 18];
scales.forEach(function(el){if(wind_speed >= el) scale++});
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-03-17 22:22:08