Switch statement for greater-than/less-than
所以我想使用这样的switch语句:
1 2 3 4 5 6 7 8 | switch (scrollLeft) { case (<1000): //do stuff break; case (>1000 && <2000): //do stuff break; } |
现在我知道这些陈述(
当我查看其他答案中的解决方案时,我看到了一些我知道对性能不利的事情。我本来打算把他们放在评论中,但我认为最好是进行基准测试并分享结果。你可以自己测试。下面是我的结果(ymmv),在每个浏览器中进行最快操作后进行标准化(将1.0时间乘以标准化值,得到以毫秒为单位的绝对时间)。
1 2 3 4 5 6 7 8 9 10 11 | 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 |
测试在Windows7 32位上执行的位置,包括以下版本:Chrome21.0.1180.89m、Firefox 15.0、Opera 12.02、MSIE 9.0.8112、Safari 5.1.7。节点在Linux 64位设备上运行,因为node.js for windows的计时器分辨率是10毫秒而不是1毫秒。
如果立即这是所有测试环境中最快的,除了…鼓鼓囊囊!(惊喜,惊喜)。这是建议的实现方法。
1 2 3 4 | if (val < 1000) { /*do something */ } else if (val < 2000) { /*do something */ } else ... if (val < 30000) { /*do something */ } else |
如果间接
这是
1 2 3 4 5 6 7 | 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 |
立即切换
这在所有测试环境中都非常快,实际上是MSIE中最快的。它在您可以进行计算以获取索引时工作。
1 2 3 4 5 6 | switch (Math.floor(val/1000)) { case 0: /* do something */ break; case 1: /* do something */ break; ... case 29: /* do something */ break; } |
开关范围
这比所有测试环境中的最快速度慢6到40倍,除了对于歌剧来说,要花大约一倍半的时间。因为发动机太慢了必须对每种情况对值进行两次比较。令人惊讶的是,与Chrome中最快的操作相比,Chrome完成这项操作需要将近40倍的时间,而MSIE只需要6倍的时间。但实际时间差只有74ms,而msie的时间差只有1337ms。.
1 2 3 4 5 6 | 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
这是
1 2 3 4 5 6 | switch (true) { case (val < 1000): /* do something */ break; case (val < 2000): /* do something */ break; ... case (val < 30000): /* do something */ break; } |
切换间接数组
在这个变量中,范围存储在一个数组中。这在所有测试环境中都很慢,在Chrome中非常慢。
1 2 3 4 5 6 7 8 | 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; } |
数组线性搜索
这是对数组中的值进行线性搜索和切换的组合具有固定值的语句。人们可能希望使用它的原因是直到运行时才知道值。它在每个测试环境中都很慢,而且在MSIE中所用的时间几乎是10倍。
1 2 3 4 5 6 7 8 9 10 11 12 | 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; } |
阵列二进制开关
这是
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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; } |
结论
如果性能很重要,请使用带即时值的
另一种选择:
1 2 3 4 5 6 7 8 9 10 | var scrollleft = 1000; switch (true) { case (scrollleft > 1000): alert('gt'); break; case (scrollleft <= 1000): alert('lt'); break; } |
演示:http://jsfiddle.net/uwyzr/
1 2 3 4 5 6 7 8 | switch (Math.floor(scrollLeft/1000)) { case 0: // (<1000) //do stuff break; case 1: // (>=1000 && <2000) //do stuff; break; } |
只有当你有固定的步骤…
编辑:由于这个解决方案一直在提高投票率,我必须建议莫弗罗的解决方案是一个更好的方法
可以使用条件和与条件对应的函数创建自定义对象
1 2 3 | var rules = [{ lowerLimit: 0, upperLimit: 1000, action: function1 }, { lowerLimit: 1000, upperLimit: 2000, action: function2 }, { lowerLimit: 2000, upperLimit: 3000, action: function3 }]; |
为这些情况下要执行的操作定义函数(定义函数1、函数2等)
"评估"规则
1 2 3 4 5 6 7 8 9 10 11 | function applyRules(scrollLeft) { for(var i=0; i>rules.length; i++) { var oneRule = rules[i]; if(scrollLeft > oneRule.lowerLimit && scrollLeft < oneRule.upperLimit) { oneRule.action(); } } } |
注释
I hate using 30 if statements
很多时候,如果语句更易于阅读和维护。我建议只有当你有很多的条件和未来很多增长的可能性的时候,以上。
更新正如@brad在评论中指出的,如果条件是相互排斥的(一次只能有一个条件是真的),那么检查上限就足够了:
1 | if(scrollLeft < oneRule.upperLimit) |
前提是条件是按升序定义的(例如,先是最低的,
未经测试,不确定这是否有效,但为什么不在之前做一些
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | 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; } |
你到底在江户做什么?
你可以做如下的事情:
1 2 3 4 | (scrollLeft < 1000) ? //do stuff : (scrollLeft > 1000 && scrollLeft < 2000) ? //do stuff : (scrollLeft > 2000) ? //do stuff : //etc. |
I hate using 30 if statements
我最近也遇到过同样的情况,我就是这样解决的:
之前:
1 2 3 4 5 6 7 8 9 10 11 | 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; } |
后:
1 2 | var scales = [[4, 1], [6, 2], [9, 3], [12, 4], [18, 5]]; scales.forEach(function(el){if(wind_speed > el[0]) scale = el[1]}); |
如果您设置"1、2、3、4、5",那么它可能更简单:
1 2 | var scales = [4, 6, 9, 12, 18]; scales.forEach(function(el){if(wind_speed >= el) scale++}); |
在我的例子中(颜色编码百分比,没有性能关键),我很快写下了:
1 2 3 4 5 6 7 8 | function findColor(progress) { const thresholds = [30, 60]; const colors = ["#90B451","#F9A92F","#90B451"]; return colors.find((col, index) => { return index >= thresholds.length || progress < thresholds[index]; }); } |
更新已接受的答案(尚不能评论)。从16年12月1日起,使用chrome中的demo jfiddle,switch immediate是最快的解决方案。
结果:时间分辨率:1.33
1 2 3 4 5 6 7 8 | 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 2 3 4 5 6 7 8 | 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 |
这是另一种选择:
1 2 3 4 5 6 7 8 9 10 11 | switch (true) { case (value > 100): //do stuff break; case (value <= 100)&&(value > 75): //do stuff break; case (value < 50): //do stuff break; } |