オブジェクトを自分で手動でハッシュし、結果の文字列を通常の JavaScript 辞書のキーとして使用します。結局のところ、あなたは自分のオブジェクトがユニークである理由を知るのに最適な立場にいます. それが私がすることです。
例:
var key = function(obj){
// Some unique object-dependent key
return obj.totallyUniqueEmployeeIdKey; // Just an example
};
var dict = {};
dict[key(obj1)] = obj1;
dict[key(obj2)] = obj2;
このようにして、メモリ割り当てやオーバーフロー処理を重くすることなく、JavaScript によって行われるインデックス作成を制御できます。
もちろん、本当に「産業レベルのソリューション」が必要な場合は、キー関数によってパラメータ化されたクラスを構築し、コンテナの必要なすべての API を使用できますが、... JavaScript を使用し、シンプルで軽量になるように努めています。したがって、この機能的なソリューションはシンプルで高速です。
鍵関数は、オブジェクトの正しい属性を選択するのと同じくらい単純にすることができます。たとえば、鍵または鍵のセット (既に一意である)、鍵の組み合わせ (互いに一意である)、またはいくつかの暗号化ハッシュを使用するのと同じくらい複雑です。DojoX encodingまたはDojoX UUIDで。後者のソリューションは一意のキーを生成する可能性がありますが、個人的には、オブジェクトを一意にするものを知っている場合は特に、それらを絶対に避けようとします。
2014 年の更新: 2008 年に回答がありましたが、この単純な解決策にはまだ説明が必要です。Q&A形式でアイデアを明確にしましょう。
あなたのソリューションには実際のハッシュがありません。それはどこにある???
JavaScript は高級言語です。その基本プリミティブ ( Object ) には、プロパティを保持するためのハッシュ テーブルが含まれています。このハッシュ テーブルは通常、効率を高めるために低水準言語で記述されます。文字列キーを持つ単純なオブジェクトを使用して、効率的に実装されたハッシュ テーブルを使用します。
彼らがハッシュを使用していることをどのように知っていますか?
オブジェクトのコレクションをキーでアドレス指定できるようにするには、主に次の 3 つの方法があります。
- 順不同。この場合、キーでオブジェクトを取得するには、すべてのキーを調べて、見つかったら停止する必要があります。平均して n/2 回の比較が必要です。
- 順序付けられました。
- 例 #1: 並べ替えられた配列 — 二分探索を行うと、平均で ~log2(n) 回の比較後にキーが見つかります。ずっといい。
- 例 #2: 木。ここでも ~log(n) 回の試行になります。
- ハッシュ表。平均して、一定の時間が必要です。比較: O(n) 対 O(log n) 対 O(1)。ブーム。
明らかに、JavaScript オブジェクトは何らかの形でハッシュ テーブルを使用して一般的なケースを処理します。
ブラウザベンダーは本当にハッシュテーブルを使用していますか???
本当。
彼らは衝突を処理しますか?
はい。上記を参照。等しくない文字列で衝突が見つかった場合は、躊躇せずにベンダーにバグを報告してください。
それで、あなたの考えは何ですか?
オブジェクトをハッシュしたい場合は、それを一意にするものを見つけてキーとして使用します。実際のハッシュを計算したり、ハッシュ テーブルをエミュレートしたりしないでください。基礎となる JavaScript オブジェクトによって既に効率的に処理されています。
このキーを JavaScript で使用Object
して、組み込みのハッシュ テーブルを活用しながら、デフォルト プロパティとの衝突の可能性を回避します。
開始するための例:
- オブジェクトに一意のユーザー名が含まれている場合は、それをキーとして使用します。
- 一意の顧客番号が含まれている場合は、それをキーとして使用します。
- 米国のSSNやパスポート番号などの政府発行の一意の番号が含まれていて、システムで重複が許可されていない場合は、それをキーとして使用します。
- フィールドの組み合わせが一意である場合は、それをキーとして使用します。
- 米国の州の略語 + 運転免許証番号が優れたキーになります。
- 国の略語 + パスポート番号も優れたキーです。
- フィールドまたはオブジェクト全体の一部の関数は、一意の値を返すことができます — それをキーとして使用します。
あなたの提案を使用し、ユーザー名を使用してすべてのオブジェクトをキャッシュしました。しかし、組み込みプロパティである「toString」という名前の賢い人もいます。私は今どうすればいい?
明らかに、結果のキーがラテン文字のみで構成される可能性がわずかでもある場合は、それについて何かを行う必要があります。たとえば、「#toString」、「#MarySmith」などのデフォルト プロパティと衝突しないように、任意の非ラテン Unicode 文字を最初または最後に追加します。複合キーを使用する場合は、ラテン語以外の区切り文字「name,city,state」を使用してキー コンポーネントを区切ります。
一般に、これは創造性を発揮し、特定の制限 (一意性、デフォルト プロパティとの衝突の可能性) を伴う最も簡単なキーを選択する必要がある場所です。
注: 一意のキーは定義上衝突しませんが、潜在的なハッシュ衝突は基礎となる によって処理されObject
ます。
産業用ソリューションが気に入らないのはなぜですか?
私見ですが、最良のコードはまったくコードがないことです。エラーがなく、メンテナンスが不要で、理解しやすく、瞬時に実行されます。私が見た「JavaScript のハッシュ テーブル」はすべて 100 行以上のコードで、複数のオブジェクトが含まれていました。と比較してくださいdict[key] = value
。
もう 1 つのポイント: JavaScript とまったく同じ原始オブジェクトを使用して、既に実装されているものを実装することで、低水準言語で記述された原始オブジェクトのパフォーマンスを超えることさえ可能ですか?
キーなしでオブジェクトをハッシュしたい!
幸運なことに、 ECMAScript 6 (2015 年 6 月にリリース) ではmapとset が定義されています。
定義から判断すると、オブジェクトのアドレスをキーとして使用できるため、人工的なキーなしでオブジェクトを即座に区別できます。2 つの異なるが同一のオブジェクトである OTOH は、別個のものとしてマッピングされます。
MDNからの比較の内訳:
オブジェクトは、キーを値に設定したり、それらの値を取得したり、キーを削除したり、キーに何かが格納されているかどうかを検出したりできるという点でマップに似ています。このため (そして組み込みの代替手段がなかったため)、オブジェクトは歴史的にマップとして使用されてきました。ただし、特定の場合に Map の使用を推奨する重要な違いがあります。
- オブジェクトのキーは文字列とシンボルですが、関数、オブジェクト、プリミティブなど、マップの任意の値にすることができます。
- Map のキーは順序付けされていますが、オブジェクトに追加されたキーは順序付けられていません。したがって、それを反復処理すると、Map オブジェクトは挿入順にキーを返します。
- Map のサイズは size プロパティで簡単に取得できますが、Object のプロパティの数は手動で決定する必要があります。
- Map は iterable であるため、直接反復できますが、Object を反復するには、何らかの方法でキーを取得し、それらを反復する必要があります。
- オブジェクトにはプロトタイプがあるため、注意しないとキーと衝突する可能性があるデフォルト キーがマップに存在します。ES5 の時点では、これは map = Object.create(null) を使用してバイパスできますが、これはめったに行われません。
- キー ペアの頻繁な追加と削除を伴うシナリオでは、Map のパフォーマンスが向上する場合があります。