大于/小于的开关语句结论

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

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

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


答案 1

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

以下是2021-MAY-05的结果

测试 火狐浏览器 歌剧 边缘 勇敢 节点
1.0 倍 15 毫秒 14 毫秒 17 毫秒 17 毫秒 16 毫秒 14 毫秒
如果-立即 1.00 1.00 1.00 1.00 1.00 1.00
如果-间接 2.20 1.21 2.06 2.18 2.19 1.93
开关-即时 2.07 1.43 1.71 1.71 2.19 1.93
开关量程 3.60 2.00 2.47 2.65 2.88 2.86
开关量程2 2.07 1.36 1.82 1.71 1.94 1.79
开关间接阵列 2.93 1.57 2.53 2.47 2.75 2.50
阵列线性开关 2.73 3.29 2.12 2.12 2.38 2.50
阵列二进制开关 5.80 6.07 5.24 5.24 5.44 5.37

2021年的测试在Windows 10 64bit上执行,具有以下版本:Chrome 90.0.4430.212Firefox 89.0b13Opera 76.0.4017.123Edge 90.0.818.62Brave 1.24.85Node 16.1.0(在WSL下运行)

苹果没有更新Windows版Safari,所以它仍然是5.1.7。在这个测试中,我把它改成了勇敢。

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

测试 火狐浏览器 歌剧 断续器 野生动物园 节点
1.0 倍 37 毫秒 73 毫秒 68 毫秒 184 毫秒 73 毫秒 21 毫秒
如果-立即 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

2012年的测试在Windows 7 32bit上进行,版本如下:Chrome 21.0.1180.89mFirefox 15.0Opera 12.02MSIE 9.0.8112Safari 5.1.7Node在Linux 64bit机器上运行,因为Node for Windows上的计时器分辨率是10ms而不是1ms。

如果-立即

这是所有测试环境中最快的方法,除了...鼓点嗯!(惊喜,惊喜)。

这是实现它的推荐方法。

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

如果-间接

这是但带有 -语句的变体,并且在所有测试的引擎中都更快。switch-indirect-arrayif

在2021年,它比最快的测试慢20-120%(2012年:0-280%)。Chrome 在 2021 年 (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

开关-即时

当您可以执行计算以获取索引时,此方法有效。

在2021年,它比慢40-120%(2012年:0-180%),除了在MSIE中它实际上是最快的。if-immediate

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

开关量程2

这是的变体,但每个案例只有一个比较,因此更快。case 语句的顺序很重要,因为引擎将按照源代码顺序测试每个案例 ECMAScript 2020 13.12.9switch-range

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

开关间接阵列

在此变体中,范围存储在数组中。

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

阵列线性搜索

在此变体中,范围存储在数组中。

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

结论

如果性能很重要,请使用带有直接值的 -语句 或 。ifswitch


答案 2

另一种选择:

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

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