大于/小于的切换语句

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

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

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

382030 次浏览

你到底在//do stuff中做什么?

你可以这样做:

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

您可以使用标准和与标准对应的函数创建一个自定义对象

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

在这些情况下定义函数(定义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个if语句

很多时候if语句更容易阅读和维护。 只有当你有很多条件的时候,我才会推荐上面的方法。< / p > < p > < >强更新< / >强 < br > 正如@Brad在评论中指出的那样,如果条件是互斥的(一次只能有一个条件为真),检查上限就足够了:

if(scrollLeft < oneRule.upperLimit)

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

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

只有当你有规律的步数时才有效……

编辑:由于这个解决方案不断得到好评,我必须建议mofolo的解决方案是一个更好的方式

未经测试,不确定这是否将工作,但为什么不做一些if statements之前,设置变量的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;
}

另一个:

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

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

这是另一种选择:

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

当我查看其他答案中的解决方案时,我看到了一些我知道对性能不利的东西。我打算把它们放在评论中,但我认为最好是基准测试并分享结果。你可以自己测试。下面是我的结果(ymmv)在每个浏览器中最快的操作后归一化。

以下是2021年5月-05日的结果

< span style=" font - family:宋体;"> < / th >铬 < span style=" font - family:宋体;"Firefox > < / th > < span style=" font - family:宋体;"歌剧> < / th > < span style=" font - family:宋体;"> < / th边缘> < span style=" font - family:宋体;"勇敢> < / th > < span style=" font - family:宋体;"< / th > >节点 < span style=" font - family:宋体;"> 15道明> < /女士 < span style=" font - family:宋体;"> 14道明> < /女士 < span style=" font - family:宋体;"> 17道明> < /女士 < span style=" font - family:宋体;"> 17道明> < /女士 < span style=" font - family:宋体;"> 16道明> < /女士 < span style=" font - family:宋体;"> 14道明> < /女士 . . font - family:宋体; < font - family:宋体 . font - family:宋体; . . . . . < font - family:宋体 . font - family:宋体; < font - family:宋体 . font - family:宋体; < font - family:宋体 . font - family:宋体; . .
测试
1.0时间
眼前的
虽然是间接的 2.18 . font - family:宋体; < font - family:宋体 . . . font - family:宋体; >
switch-indirect-array .
array-linear-switch . font - family:宋体; .

2021年的测试在Windows 10 64位上执行,版本如下:Chrome 90.0.4430.212Firefox 89.0十三区最歌剧76.0.4017.123边缘90.0.818.62勇敢1.24.85节点16.1.0(在WSL下运行)

苹果没有更新Safari for Windows,所以它仍然是5.1.7。我在这次测试中把它改成了Brave。

以下是2012年9月至2004年的结果,用于历史比较:

< span style=" font - family:宋体;"> < / th >铬 < span style=" font - family:宋体;"Firefox > < / th > < span style=" font - family:宋体;"歌剧> < / th > < span style=" font - family:宋体;"> MSIE < / th > < span style=" font - family:宋体;"Safari > < / th > < span style=" font - family:宋体;"< / th > >节点 < span style=" font - family:宋体;"> 37道明> < /女士 < span style=" font - family:宋体;"> 73 ms td > < / < span style=" font - family:宋体;"> 68 ms td > < / < span style=" font - family:宋体;"> 184 ms td > < / < span style=" font - family:宋体;"> 73 ms td > < / < span style=" font - family:宋体;"21女士> < / td > < font style=" font - family:宋体; < font - family:宋体> " font - family:宋体; 3. . " font - family:宋体; < span style=" font - family:宋体; 6 . . " font - family:宋体; . < font - family:宋体 . font - family:宋体; . . . < font - family:宋体 . font - family:宋体; 6 . . . . " font - family:宋体; . < d style="text-align: center; >10.0 4. . " font - family:宋体; 2. . " font - family:宋体; . " font - family:宋体; 6. . " font - family:宋体; 9. . " font - family:宋体; . " font - family:宋体; .
测试
1.0时间
眼前的
虽然是间接的 . " font - family:宋体; 20.9
switch-range2 . " font - family:宋体; 9 .
switch-indirect-array . font - family:宋体; 4.
array-binary-switch .

2012年的测试在Windows 7 32位上执行,版本如下:Chrome 21.0.1180.89mFirefox 15.0Opera 12.02MSIE 9.0.8112Safari 5.1.7节点在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的变体,但使用__abc1 -语句代替,在所有测试引擎中都更快。

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只有一个比较,因此更快。 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

这是array-linear-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-statements或switch,并带有立即值。

更新已接受的答案(还不能评论)。截至2016年1月12日在chrome中使用演示jsfiddle, switch-immediate是最快的解决方案。

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

在我的例子中(用颜色编码百分比,没有任何性能关键),我很快写下了这样的内容:

function findColor(progress) {
const thresholds = [30, 60];
const colors = ["#90B451", "#F9A92F", "#90B451"];


return colors.find((col, index) => {
return index >= thresholds.length || progress < thresholds[index];
});
}

我讨厌使用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++});