切换语句大于/小于

所以我想用这样的switch语句:

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

现在我知道这些语句( <1000 )或( >1000 && <2000 )中的任何一个都不起作用(显然是出于不同的原因)。 我所要求的是最有效的方法。 我讨厌使用30条if语句,所以我宁愿使用switch语法。 有什么我能做的吗?

当我在其他答案中看到解决scheme时,我看到了一些我知道对性能不好的东西。 我将要发表评论,但是我认为最好是对它进行基准testing并分享结果。 你可以自己testing一下 。 下面是我的结果(ymmv)在每个浏览器中最快的操作之后归一化(将1.0倍的时间乘以归一化的值以绝对时间为单位)。

                     Chrome Firefox Opera MSIE Safari节点
 -------------------------------------------------- -----------------
 1.0次37ms 73ms 68ms 184ms 73ms 21ms
 if-immediate 1.0 1.0 1.0 2.6 1.0 1.0
如果 - 间接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
开关范围38.1 10.6 2.6 7.3 20.9 10.4
开关范围2 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
arrays线性开关3.6 4.1 4.5 10.0 4.7 2.7
arrays二进制开关7.8 6.7 9.5 16.0 15.0 4.9

testing在Windows 7 32位上执行以下版本: Chrome 21.0.1180.89mFirefox 15.0Opera 12.02MSIE 9.0.8112Safari 5.1.7节点运行在Linux 64位盒子上,因为Node.js for Windows上的计时器分辨率是10ms而不是1ms。

如果,即时

这是所有testing环境中速度最快的,除了… drumroll MSIE! (惊喜,惊喜)。 这是实施它的推荐方法。

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

如果间接

这是switch-indirect-array一个变体,但是在if语句的情况下,在几乎所有的testing环境中,它的执行速度要比switch-indirect-array快得多。

 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 

开关,立即

这在所有testing环境中都非常快,实际上是MSIE中速度最快的。 它可以工作,当你可以做一个计算来获得索引。

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

开关范围

这比所有testing环境中最快的速度慢了6到40倍,除了Opera,大约需要一倍半的时间。 这很慢,因为引擎必须比较两个值的情况。 令人惊讶的是,与Chrome上运行速度最快的操作系统相比,Chrome的运行速度要快40倍,而MSIE只能运行6次。 但在1337ms(!),实际的时差仅为74ms,有利于MSIE。

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

开关范围2

这是一个switch-range的变体,但每个案件只有一个比较,因此速度更快,但除Opera以外仍然非常缓慢。 case语句的顺序很重要,因为引擎会以源代码的顺序testing每个case ECMAScript262:12.11

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

切换-间接arrays

在这个变体中,范围被存储在一个数组中。 这在所有testing环境中都很慢,而且在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; } 

arrays线性search

这是一个线性search数组中值的结合,以及具有固定值的开关语句。 人们可能想要使用它的原因是直到运行时才知道这些值。 它在每个testing环境中都很慢,而且在MSIE中要花费近10倍的时间。

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

arrays二进制开关

这是一个array-linear-switch的变体,但是具有二进制search。 不幸的是它比线性search慢。 我不知道这是我的实现还是线性search更加优化。 它也可能是密钥空间很小。

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

结论

如果性能很重要,请使用if -statements或使用即时值进行switch

替代:

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

演示: http : //jsfiddle.net/UWYzr/

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

只有当你有规律的步骤

编辑:因为这个解决scheme不断得到upvotes,我必须build议, mofolo的解决scheme是一个更好的方法

您可以使用与标准对应的标准和function创build自定义对象

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

在这些情况下定义你想要做的function(定义function1,function2等)

并“评估”规则

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

注意

我讨厌使用30条语句

很多时候,如果陈述更容易阅读和维护。 只有当你有很多的条件未来有很大的增长的可能性,我才会推荐以上。

更新
正如@Brad在评论中指出的那样,如果条件是相互排斥的(一次只能有一个是真的),那么检查上限就足够了:

 if(scrollLeft < oneRule.upperLimit) 

条件是按升序定义(例如,首先是最低的一个,例如0 to 1000 ,然后是1000 to 2000

未经testing和不确定这是否可行,但为什么不做一些if statements之前,为switch statement设置variables。

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

你到底在//do stuff

您可能可以执行如下操作:

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

在我的情况下(颜色编码的百分比,没有性能关键),我很快写了这样的:

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

这是另一个select:

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

更新接受的答案(不能评论)。 在1/12/16使用chrome中的demo jsfiddle,switch-immediate是最快的解决scheme。

结果:时间分辨率: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 

成品

  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