切换语句大于/小于

swi*_*itz 212 javascript comparison jquery switch-statement

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

switch (scrollLeft) {
  case (<1000):
   //do stuff
   break;
  case (>1000 && <2000):
   //do stuff
   break;
}
Run Code Online (Sandbox Code Playgroud)

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

som*_*ome 669

当我在其他答案中查看解决方案时,我看到一些我知道对性能有害的事情.我打算将它们放在评论中,但我认为最好对它进行基准测试并分享结果.你可以自己测试一下.下面是我的结果(ymmv)在每个浏览器中最快的操作之后归一化(将1.0时间乘以标准化值以获得以ms为单位的绝对时间).

                    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

使用以下版本测试在Windows 7 32位上执行的操作:Chrome 21.0.1180.89m,Firefox 15.0,Opera 12.02,MSIE 9.0.8112,Safari 5.1.7.节点在Linux 64位盒上运行,因为Node.js for Windows上的计时器分辨率是10ms而不是1ms.

如果,即时

这是所有测试环境中最快的,除了...... drumroll MSIE!(惊讶,惊讶).这是实现它的推荐方法.

if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
Run Code Online (Sandbox Code Playgroud)

如果间接

这是一种变体,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
Run Code Online (Sandbox Code Playgroud)

开关,立即

这在所有测试环境中都非常快,实际上是MSIE中最快的.它可以在您进行计算以获取索引时起作用.

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

开关范围

这比所有测试环境中最快的速度慢6到40倍,除了Opera需要大约1.5倍的时间.它很慢,因为引擎必须为每种情况比较两次值.令人惊讶的是,与Chrome中最快的操作相比,Chrome完成此操作所需的时间要长近40倍,而MSIE只需要6倍的时间.但实际时差仅为74毫秒,有利于MSIE为1337毫秒(!).

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;
}
Run Code Online (Sandbox Code Playgroud)

开关范围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;
}
Run Code Online (Sandbox Code Playgroud)

切换-间接阵列

在该变体中,范围存储在阵列中.这在所有测试环境中都很慢,而在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;
}
Run Code Online (Sandbox Code Playgroud)

阵列线性搜索

这是对数组中值的线性搜索和具有固定值的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;
}
Run Code Online (Sandbox Code Playgroud)

阵列二进制开关

这是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;
}
Run Code Online (Sandbox Code Playgroud)

结论

如果性能很重要,请使用if-statements或switch使用立即值.

  • 很难看到这个细节和整洁结构的答案.大+1 (111认同)
  • 这就是stackoverflow是最佳答案之一的原因.这是一个"永恒"的答案,很棒的工作,并感谢jsfiddle! (13认同)
  • 大+1为这个问题的性能方面的解释! (9认同)
  • grt信息和解释 (2认同)
  • 我真的希望我能+2,这么详细的答案! (2认同)

lab*_*bue 89

替代:

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

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

  • 虽然优雅的代码,但它会伤害性能.Chrome中使用"if"语句的速度几乎要慢30倍.看我的[这里回答](http://stackoverflow.com/a/12259830/36866) (7认同)
  • 这是一个更有价值的解决方案.+1 (4认同)
  • 这不是和 `if(...) else if(...)` 一样吗?这确实避免了`if`,但对我来说听起来并不像一个漂亮的替代品。 (2认同)

Ica*_*By0 21

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

只有经常步骤才有效...

编辑:由于这个解决方案不断上升,我必须建议mofolo的解决方案更好


Niv*_*vas 6

您可以使用与条件对应的条件和功能创建自定义对象

var rules = [{ lowerLimit: 0,    upperLimit: 1000, action: function1 }, 
             { lowerLimit: 1000, upperLimit: 2000, action: function2 }, 
             { lowerLimit: 2000, upperLimit: 3000, action: function3 }];
Run Code Online (Sandbox Code Playgroud)

在这些情况下定义您想要做的功能(定义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();
       }
   }
}
Run Code Online (Sandbox Code Playgroud)

注意

我讨厌使用30 if语句

很多时候if语句更容易阅读和维护.只有当你有很多条件并且未来可能会有很多增长时,我才会推荐上述内容.

更新
为@Brad在注释中指出,如果条件是互斥的(一次只能其中一个为真),检查上限应该足够了:

if(scrollLeft < oneRule.upperLimit)
Run Code Online (Sandbox Code Playgroud)

提供该条件以升序定义(第一最低,0 to 1000,然后1000 to 2000例如)