所以我想用这样的switch语句:
switch (scrollLeft) {
case (<1000):
//do stuff
break;
case (>1000 && <2000):
//do stuff
break;
}
现在我知道这些语句(<1000)或(>1000 && <2000)中的任何一个都不会工作(显然是由于不同的原因)。我问的是最有效的方法。我讨厌使用30个if语句,所以我宁愿使用switch语法。我能做些什么吗?
所以我想用这样的switch语句:
switch (scrollLeft) {
case (<1000):
//do stuff
break;
case (>1000 && <2000):
//do stuff
break;
}
现在我知道这些语句(<1000)或(>1000 && <2000)中的任何一个都不会工作(显然是由于不同的原因)。我问的是最有效的方法。我讨厌使用30个if语句,所以我宁愿使用switch语法。我能做些什么吗?
当前回答
当我查看其他答案中的解决方案时,我看到了一些我知道对性能不利的东西。我打算把它们放在评论中,但我认为最好是基准测试并分享结果。你可以自己测试。下面是我的结果(ymmv)在每个浏览器中最快的操作后归一化。
以下是2021年5月-05日的结果
Test | Chrome | Firefox | Opera | Edge | Brave | Node |
---|---|---|---|---|---|---|
1.0 time | 15 ms | 14 ms | 17 ms | 17 ms | 16 ms | 14 ms |
if-immediate | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 |
if-indirect | 2.20 | 1.21 | 2.06 | 2.18 | 2.19 | 1.93 |
switch-immediate | 2.07 | 1.43 | 1.71 | 1.71 | 2.19 | 1.93 |
switch-range | 3.60 | 2.00 | 2.47 | 2.65 | 2.88 | 2.86 |
switch-range2 | 2.07 | 1.36 | 1.82 | 1.71 | 1.94 | 1.79 |
switch-indirect-array | 2.93 | 1.57 | 2.53 | 2.47 | 2.75 | 2.50 |
array-linear-switch | 2.73 | 3.29 | 2.12 | 2.12 | 2.38 | 2.50 |
array-binary-switch | 5.80 | 6.07 | 5.24 | 5.24 | 5.44 | 5.37 |
2021年的测试在Windows 10 64bit上进行,版本如下:Chrome 90.0.4430.212, Firefox 80.9 b13, Opera 76.0.4017.123, Edge 90.0.818.62, Brave 1.24.85和Node 16.1.0(在WSL下运行)
苹果没有针对Windows更新Safari,所以它仍然是5.1.7版本。我在这次测试中把它改成了Brave。
以下是2012年9月至2004年的结果,用于历史比较:
Test | Chrome | Firefox | Opera | MSIE | Safari | Node |
---|---|---|---|---|---|---|
1.0 time | 37 ms | 73 ms | 68 ms | 184 ms | 73 ms | 21 ms |
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 |
2012年的测试在Windows 7 32位上进行,版本如下:Chrome 21.0.1180.89m, Firefox 15.0, Opera 12.02, MSIE 9.0.8112, Safari 5.1.7。Node运行在Linux 64位机器上,因为Node for Windows上的计时器分辨率是10ms而不是1ms。
眼前的
这是所有测试环境中最快的方法,除了……击鼓MSIE !(震惊)。
这是推荐的实现方法。
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
虽然是间接的
这是switch-indirect-array的变体,但是使用if语句代替,并且在所有测试引擎中都更快。
2021年比最快的测试慢了20-120%(2012年:0-280%)。2021年Chrome浏览器使用时间(2.20)比2012年(1.2)更长
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
当您可以通过计算来获得索引时,这种方法是有效的。
在2021年,它比if-immediate慢了40-120%(2012年:0-180%),除了在MSIE中它实际上是最快的。
switch (Math.floor(val/1000)) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
量程切换
它很慢,因为引擎必须对每种情况的值进行两次比较。
在2021年,它比最快的测试慢了1-2.6倍(2012年:1.6-38倍)。 Chrome从38到3.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;
}
switch-range2
这是switch-range的变体,但每个情况只有一个比较,因此更快。 case语句的顺序很重要,因为引擎将按照源代码顺序ECMAScript 2020 13.12.9测试每个case
在2021年,它比最快的测试慢了36-107%,但在2012年,它慢了1-31倍。在这次测试中,Chrome仍然是表现最差的,但它已经从32倍提高到了2倍。
switch (true) {
case (val < 1000): /* do something */ break;
case (val < 2000): /* do something */ break;
...
case (val < 30000): /* do something */ break;
}
switch-indirect-array
在这个变体中,范围存储在一个数组中。
在2021年,比最快的测试慢了57-193%(2012年:3-35倍)。 所有测试引擎的性能都有所提高,虽然Chrome仍然是最慢的,但它已经从35提升到了2.93。
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
在这个变体中,范围存储在一个数组中。
在2021年,比最快的测试慢了57-193%(2012年:3-35倍)。 所有测试引擎的性能都有所提高,虽然Chrome仍然是最慢的,但它已经从35提升到了2.93。
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
这是数组-线性切换的一种变体,但带有二进制搜索。 不幸的是,它比线性搜索慢。我不知道这是我的实现还是线性搜索更优化。也可能是密钥空间太小了。
到2021年,这一数字下降了4-5倍(2012年为4-16倍)。不要使用。
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语句或switch,并带有立即值。
其他回答
当我查看其他答案中的解决方案时,我看到了一些我知道对性能不利的东西。我打算把它们放在评论中,但我认为最好是基准测试并分享结果。你可以自己测试。下面是我的结果(ymmv)在每个浏览器中最快的操作后归一化。
以下是2021年5月-05日的结果
Test | Chrome | Firefox | Opera | Edge | Brave | Node |
---|---|---|---|---|---|---|
1.0 time | 15 ms | 14 ms | 17 ms | 17 ms | 16 ms | 14 ms |
if-immediate | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 |
if-indirect | 2.20 | 1.21 | 2.06 | 2.18 | 2.19 | 1.93 |
switch-immediate | 2.07 | 1.43 | 1.71 | 1.71 | 2.19 | 1.93 |
switch-range | 3.60 | 2.00 | 2.47 | 2.65 | 2.88 | 2.86 |
switch-range2 | 2.07 | 1.36 | 1.82 | 1.71 | 1.94 | 1.79 |
switch-indirect-array | 2.93 | 1.57 | 2.53 | 2.47 | 2.75 | 2.50 |
array-linear-switch | 2.73 | 3.29 | 2.12 | 2.12 | 2.38 | 2.50 |
array-binary-switch | 5.80 | 6.07 | 5.24 | 5.24 | 5.44 | 5.37 |
2021年的测试在Windows 10 64bit上进行,版本如下:Chrome 90.0.4430.212, Firefox 80.9 b13, Opera 76.0.4017.123, Edge 90.0.818.62, Brave 1.24.85和Node 16.1.0(在WSL下运行)
苹果没有针对Windows更新Safari,所以它仍然是5.1.7版本。我在这次测试中把它改成了Brave。
以下是2012年9月至2004年的结果,用于历史比较:
Test | Chrome | Firefox | Opera | MSIE | Safari | Node |
---|---|---|---|---|---|---|
1.0 time | 37 ms | 73 ms | 68 ms | 184 ms | 73 ms | 21 ms |
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 |
2012年的测试在Windows 7 32位上进行,版本如下:Chrome 21.0.1180.89m, Firefox 15.0, Opera 12.02, MSIE 9.0.8112, Safari 5.1.7。Node运行在Linux 64位机器上,因为Node for Windows上的计时器分辨率是10ms而不是1ms。
眼前的
这是所有测试环境中最快的方法,除了……击鼓MSIE !(震惊)。
这是推荐的实现方法。
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
虽然是间接的
这是switch-indirect-array的变体,但是使用if语句代替,并且在所有测试引擎中都更快。
2021年比最快的测试慢了20-120%(2012年:0-280%)。2021年Chrome浏览器使用时间(2.20)比2012年(1.2)更长
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
当您可以通过计算来获得索引时,这种方法是有效的。
在2021年,它比if-immediate慢了40-120%(2012年:0-180%),除了在MSIE中它实际上是最快的。
switch (Math.floor(val/1000)) {
case 0: /* do something */ break;
case 1: /* do something */ break;
...
case 29: /* do something */ break;
}
量程切换
它很慢,因为引擎必须对每种情况的值进行两次比较。
在2021年,它比最快的测试慢了1-2.6倍(2012年:1.6-38倍)。 Chrome从38到3.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;
}
switch-range2
这是switch-range的变体,但每个情况只有一个比较,因此更快。 case语句的顺序很重要,因为引擎将按照源代码顺序ECMAScript 2020 13.12.9测试每个case
在2021年,它比最快的测试慢了36-107%,但在2012年,它慢了1-31倍。在这次测试中,Chrome仍然是表现最差的,但它已经从32倍提高到了2倍。
switch (true) {
case (val < 1000): /* do something */ break;
case (val < 2000): /* do something */ break;
...
case (val < 30000): /* do something */ break;
}
switch-indirect-array
在这个变体中,范围存储在一个数组中。
在2021年,比最快的测试慢了57-193%(2012年:3-35倍)。 所有测试引擎的性能都有所提高,虽然Chrome仍然是最慢的,但它已经从35提升到了2.93。
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
在这个变体中,范围存储在一个数组中。
在2021年,比最快的测试慢了57-193%(2012年:3-35倍)。 所有测试引擎的性能都有所提高,虽然Chrome仍然是最慢的,但它已经从35提升到了2.93。
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
这是数组-线性切换的一种变体,但带有二进制搜索。 不幸的是,它比线性搜索慢。我不知道这是我的实现还是线性搜索更优化。也可能是密钥空间太小了。
到2021年,这一数字下降了4-5倍(2012年为4-16倍)。不要使用。
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语句或switch,并带有立即值。
另一个:
var scrollleft = 1000;
switch (true)
{
case (scrollleft > 1000):
alert('gt');
break;
case (scrollleft <= 1000):
alert('lt');
break;
}
演示:http://jsfiddle.net/UWYzr/
switch (Math.floor(scrollLeft/1000)) {
case 0: // (<1000)
//do stuff
break;
case 1: // (>=1000 && <2000)
//do stuff;
break;
}
只有当你有规律的步数时才有效……
编辑:由于这个解决方案不断得到点赞,我必须建议mofolo的解决方案是一个更好的方式
我讨厌使用30个if语句
我最近也遇到了同样的情况,我是这样解决的:
之前:
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;
}
后:
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”,那么它可以更简单:
var scales = [4, 6, 9, 12, 18];
scales.forEach(function(el){if(wind_speed >= el) scale++});
这是另一种选择:
switch (true) {
case (value > 100):
//do stuff
break;
case (value <= 100)&&(value > 75):
//do stuff
break;
case (value < 50):
//do stuff
break;
}