「何かをする」が異なる値を持つ同様のフォームを共有している場合、値をマップに入れ、文字列をキーとして使用できます。たとえば、長さの単位が異なる多くの数値を処理する必要があり、それらをすべてメートルに変換したいとします。
var conversionToMeters = {
"inch": 0.0254,
"inches": 0.0254,
"foot": 0.3048,
"feet": 0.3048,
"cubit": 0.4572,
"cubits": 0.4572,
"yard": 0.9144,
"yards": 0.9144,
"kilometer": 1000,
"kilometers": 1000,
"mile": 1609.344,
"miles": 1609.344,
"lightyear": 9.46e15,
"lightyears": 9.46e15,
"parsec": 3.09e16,
"parsecs": 3.09e16,
}
(略語 (「km」など) と国際的なスペル (「キロメートル」など) は、簡潔にするために省略されています。) 作成のオーバーヘッドを避けるために、事前にそのマップを準備できます。length
などの変数を指定すると、次のlength = "80 miles"
ことができます。
var magnitude = length.replace(/[\D]/g, "");
var unit = length.replace(/[\d\s]/g, "");
var lengthInMeters = magnitude * conversionToMeters[unit];
alert(lengthInMeters + " meters"); // Ta-da!
「何かをする」が共通のコードを共有していない場合でも、マップを使用できますが、関数のマップになります。
var actions = {
"eat": function() {
if (spareFood > 0) {
spareFood--;
energy += 10;
health++;
alert("Yum!");
}
},
"walk": function() {
if (energy > 0) energy--;
// ...
},
"attack": function() {
if (energy > 0) {
if (Math.random() < 0.25) {
health--;
alert("Ouch!");
}
energy--;
}
},
// ...
};
これはちょっとばかげた例ですが、基本的な考え方を説明できれば幸いです。アクションは、XML タグ、仮想マシンの CPU 命令の名前、または特別な出荷要件を持つ製品の名前などでも構いません。変数を取得したらaction
、それを実行するのは次のように簡単です。
actions[action]();
このようなことを行う方法はマップだけではありません。元の if/else の例は、ほとんどの候補文字列をすばやく削除するように設計された追加の if 内に if をネストすることで、簡単に最適化できます。
分岐する基準は、作業している正確な文字列によって異なります。文字列の長さ、最初の文字、またはいくつかの最も特徴的な文字である可能性があります。
if (str.length === 3) {
// test all length 3 strings here
if (str === strA) doSomething();
else if (str == strB) doSomething();
} else if (str.length === 4) {
// test all length 4 strings here
if (str === strC) doSomething();
else if (str === strD) doSomething();
}
または:
var first = str[0]; // first character
if (first >= "0" && first <= "9") {
// test all strings that start with digits here
if (first >= "a" && first <= "l") {
// test all strings that start with letters
// in the first half of the alphabet here
} else if (first >= "m" && first <= "z") {
// test all strings that start with letters
// in the latter half of the alphabet here
}
これらの種類のテストは、使用している特定の文字列をふるいにかけるのに適切な程度に、互いに入れ子にすることができます。これは展開された二分探索の一種ですが、分岐する基準によって候補文字列が正確に 2 つのグループに分割される必要はありません。
また、このように if/elseif を使用する場合は、頻度の高い順に文字列を並べるとよい場合がよくあります。つまり、最も多く発生するものを最初にテストします。データの大部分を占める文字列が 2、3 個しかない場合は、それらを先頭に移動し、長さや最初の文字に基づく事前テストの対象外にすることもできます。
これらのことを行う価値があるかどうかを判断する必要があります。これらの手法を極端に使用すると、パフォーマンス上の利点をわずかに追加できる可能性がありますが、読みやすさと保守性が犠牲になります。
PS 私はこれらの手法がどのように機能するかを正確に知るほど JavaScript をよく知りませんが、Java で同様のことを行いました。Java では、"何かを行う" ために異なる値が必要であるが、同じコードを使用できる場合、map アプローチは無敵です。別のプログラムではswitch
、整数値に対して約 400 の異なるアクションを実行する必要がありました (ひどいものでした)。HotSpot クライアント VM には、お粗末で非効率的な実装があります。switch
単に多くの elseif であるステートメントであり、遅すぎました。関数の配列 (技術的には仮想メソッドがオーバーライドされたオブジェクト) の方が高速でしたが、各アクションの単純さに比べて関数呼び出しのオーバーヘッドが大きすぎました。この場合、2 項と 4 項の混合検索が効果的であることがわかりました。つまり、外側のテストは、入力値を 2 つのグループに均等に分割する if/else でした。これらは、内側のグループに残る可能な値が 4 つになるまで入れ子にされました。次に、if/elseif/elseif/else を使用して、残りの 4 つの値を区別しました。これは非常に長いので、コードを書いて自分で書きましたが、この特定のアプリケーションのために努力する価値はありました。
PPS 上記でスキップしたアプローチがありますが、完全を期すために含めます。文字列を変更する必要がほとんどない場合は、完全なハッシュ関数を使用できます。これらの関数を設計するユーティリティ プログラムがあります。すべての文字列のリストを提供するだけです。完全なハッシュ関数は、文字列から整数のハッシュコードを計算し、セットの 2 つの文字列が同じハッシュコードを持たないことを保証します。次に、配列内のアクションの検索に整数ハッシュコードを使用できます。プログラミング言語のキーワードの解析などに役立ちます。金属に近い言語ではより高速になる可能性がありますが、JavaScript ではその価値はないと思います。念のため申し上げておきます。