他の回答の解決策を見ると、パフォーマンスに悪いことがわかっていることがわかりました。私はそれらをコメントに入れるつもりでしたが、それをベンチマークして結果を共有した方が良いと思いました。自分でテストできます。以下は、各ブラウザーで最速の操作の後に正規化された私の結果(ymmv)です(1.0時間に正規化された値を掛けて、絶対時間(ms)を取得します)。
Chrome Firefox Opera MSIE Safariノード
-------------------------------------------------- -----------------
1.0時間37ms 73ms 68ms 184ms 73ms 21ms
if-immediate 1.0 1.0 1.0 2.6 1.0 1.0
if間接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.89m、Firefox 15.0、Opera 12.02、MSIE 9.0.8112、Safari 5.1.7。Node.js for Windowsのタイマー解像度が1msではなく10msだったため、NodeはLinux 64ビットボックスで実行されました。
if-immediate
これは、... ドラムロール MSIE を除いて、すべてのテスト済み環境で最速です。(驚き、驚き)。これは、これを実装するための推奨される方法です。
if (val < 1000) { /*do something */ } else
if (val < 2000) { /*do something */ } else
...
if (val < 30000) { /*do something */ } else
間接的
これはのバリアントです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;
}
スイッチ範囲
これは、約1.5倍の時間がかかるOperaを除いて、テストされたすべての環境での最高速よりも約6〜40倍遅くなります。エンジンは各ケースで値を2回比較する必要があるため、処理が遅くなります。驚いたことに、MSIEは6倍の時間しか要しませんが、Chromeは最速の操作と比較して、これを完了するのに約40倍長くかかります。しかし、実際の時間差は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
が、ケースごとに比較が1つしかないため、高速ですが、Operaを除いて非常に低速です。エンジンは各ケースをソースコード順に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
-statementsまたはswitch
即値を使用してください。