一尘不染

大于/小于的切换语句

javascript

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

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

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


阅读 322

收藏
2020-04-25

共1个答案

一尘不染

当我查看其他答案中的解决方案时,我看到了一些我知道对性能不利的东西。我本来要对它们发表评论,但我认为最好对其进行基准测试并分享结果。您可以自己进行测试。下面是我在每个浏览器中以最快的速度操作后归一化的结果(ymmv)(将1.0的时间乘以归一化的值得出以毫秒为单位的绝对时间)。

                    Chrome Firefox Opera MSIE Safari节点
-------------------------------------------------- -----------------
1.0时间37ms 73ms 68ms 184ms 73ms 21ms
如果立即1.0 1.0 1.0 2.6 1.0 1.0
如果间接1.2 1.8 3.3 3.8 2.6 1.0
即时交换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
开关间接阵列35.2 9.6 4.2 5.5 10.7 8.6
阵列线性开关3.6 4.1 4.5 10.0 4.7 2.7
数组二进制开关7.8 6.7 9.5 16.0 15.0 4.9

测试在以下版本的Windows 7 32位上执行的位置: Chrome 21.0.1180.89mFirefox 15.0Opera
12.02
MSIE 9.0.8112 ,Safari5.1.7。_Node_在Linux64位机上运行,​​因为Windows的Node.js上的计时器分辨率为10ms,而不是1ms。

如果立即

这是在所有经过测试的环境中最快的速度,除了… 感光鼓 MSIE!(惊喜)。这是推荐的实现方法。

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

如果间接

这是-statement 的变体,switch-indirect-array但是具有if-statements,并且比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

立即切换

在所有经过测试的环境中,这都是相当快的,实际上是MSIE中最快的。当您可以进行计算以获取索引时,它会起作用。

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

开关范围

这比所有经过测试的环境中最快的速度慢6至40倍,Opera所需的时间大约是其一半左右。这很慢,因为引擎必须针对每种情况对值进行两次比较。令人惊讶的是,与Chrome中最快的操作相比,Chrome需要近40倍的时间来完成此操作,而MSIE只需6倍的时间。但是实际的时差仅为74ms,而MSIE为1337ms(!)。

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语句的顺序很重要,因为引擎将按源代码顺序ECMAScript262:5
12.11
测试每个案例。

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

开关间接阵列

在此变体中,范围存储在数组中。在所有经过测试的环境中,速度很慢;在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;
}

阵列线性搜索

这是对数组中的值进行线性搜索以及使用固定值的switch语句的组合。可能要使用它的原因是,直到运行时才知道这些值。在每个经过测试的环境中,它的速度都很慢,而在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;
}

阵列二进制开关

这是的变体,array-linear- switch但带有二进制搜索。不幸的是,它比线性搜索要慢。我不知道这是我的实现还是线性搜索是否更优化。键空间也可能很小。

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-statement或switch立即数。

2020-04-25