web-dev-qa-db-ja.com

キー/値ペアのJavascriptのオブジェクトと配列

非常に単純なデータ構造があるとします。

(personId, name)

...そして、これらの多くをjavascript変数に保存したい。ご覧のとおり、次の3つのオプションがあります。

// a single object
var people = {
    1 : 'Joe',
    3 : 'Sam',
    8 : 'Eve'
};

// or, an array of objects
var people = [
    { id: 1, name: 'Joe'},
    { id: 3, name: 'Sam'},
    { id: 8, name: 'Eve'}
];

// or, a combination of the two
var people = {
    1 : { id: 1, name: 'Joe'},
    3 : { id: 3, name: 'Sam'},
    8 : { id: 8, name: 'Eve'}
};

2つ目または3つ目のオプションは、保存する「値」部分が複数ある場合(またはその可能性があると予想される場合)の方法です(たとえば、年齢などを追加する)。この構造に必要なデータ値がこれ以上ないことを想定してみましょう。どちらを選択しますか?その理由は?


編集:この例は、最も一般的な状況、つまり非順次IDを示しています。

78
nickf

各ソリューションにはユースケースがあります。

1対1の関係(単純なマッピングなど)を定義しようとしている場合、特にキーをルックアップキーとして使用する必要がある場合は、最初のソリューションが良いと思います。

2番目のソリューションは、一般的に私にとって最も堅牢であると感じており、高速なルックアップキーが必要ない場合はおそらく使用します。

  • 自己記述的であるため、キーがユーザーのIDであることを知るためにpeopleを使用している人に依存する必要はありません。
  • 各オブジェクトは自己完結型であるため、データを他の場所に渡すのに適しています。2つのパラメーター(idとname)の代わりに、単に人に渡すだけです。
  • これはまれな問題ですが、キー値がキーとして使用するには有効でない場合があります。たとえば、かつて文字列変換(たとえば、 ":"を ">"に)にマッピングしたかったのですが、 ":"は有効な変数名ではないため、2番目の方法を使用する必要がありました。
  • 行に沿ってどこかで(またはすべての)一部のユーザーにデータを追加する必要がある場合は、簡単に拡張できます。 (申し訳ありませんが、「議論のため」については知っていますが、これは重要な側面です。)

3番目は、速い検索時間+上記の利点のいくつか(データの受け渡し、自己記述的)が必要な場合に適しています。ただし、ルックアップ時間を短縮する必要がない場合は、はるかに面倒です。また、どちらの方法でも、オブジェクトのIDがpeopleのIDと何らかの形で異なる場合、エラーのリスクが発生します。

57
Daniel Lew

実際には、4番目のオプションがあります。

var people = ['Joe', 'Sam', 'Eve'];

あなたの値はたまたま連続しているからです。 (もちろん、1つを追加/減算する必要があります---または最初の要素としてundefinedを配置するだけです)。

個人的には、私はあなたの(1)または(3)と一緒に行きます、なぜならそれらはID(O logn 最悪の場合)。 (2)でid 3を見つける必要がある場合は、インデックス(この場合、my(4)は大丈夫です)で検索するか、O(n)を検索する必要があります。

明確化:O(logと言うn)は最悪の場合です。なぜなら、私の知る限り、実装ではハッシュテーブルの代わりにバランスの取れたツリーを使用することを決定できるからです。衝突が最小限であると仮定すると、ハッシュテーブルはO(1)になります。

nickfからの編集:私はOPの例を変更したので、この答えはもはや意味をなさないかもしれません。謝罪。

後編集

編集後、オプション(3)を選択します。拡張可能で(新しい属性を簡単に追加できます)、高速なルックアップを備えており、同様に反復することができます。また、必要に応じて、エントリからIDに戻ることもできます。

オプション(1)は、(a)メモリを節約する必要がある場合に役立ちます。 (b)オブジェクトからidに戻る必要はありません。 (c)保存されたデータを拡張することはありません(たとえば、人の姓を追加することはできません)

オプション(2)は、(a)順序を保持する必要がある場合に適しています。 (b)すべての要素を繰り返す必要がある。 (c)idでソートされない限り、idで要素を検索する必要はありません(O(logでバイナリ検索を実行できますn)。もちろん、ソートを維持する必要がある場合は、挿入時にコストを支払うことに注意してください。

7
derobert

データが決して変更されないと仮定すると、最初の(単一オブジェクト)オプションが最適です。

構造の単純さは、解析が最も速いことを意味し、このような小さな、めったに(またはまったく)変更されないデータセットの場合、頻繁に実行されることしか想像できません-その場合、最小のオーバーヘッドは行く方法。

2
karim79

キーと値のペアを管理する小さなライブラリを作成しました。

https://github.com/scaraveos/keyval.js#readme

それは使用しています

  • キーを保存するオブジェクト。これにより、高速な削除および値の取得操作が可能になり、
  • 非常に高速な値の反復を可能にするリンクリスト

それが役に立てば幸い :)

2
scaraveos

3番目のオプションは、将来を見据えたアプリケーションに最適です。個人レコードにさらにフィールドを追加することをお勧めします。そのため、最初のオプションは不適切です。また、保存する人が多く、レコードをすばやく検索する必要がある可能性が非常に高いため、レコードを単純な配列にダンプすることも(オプション#2で行われているように)良い考えではありません。

3番目のパターンは、任意の文字列をIDとして使用し、複雑なPerson構造を持ち、一定の時間で個人レコードを取得および設定するオプションを提供します。それは間違いなく行く方法です。

オプション#3に欠けていることの1つは、安定した決定論的順序付けです(オプション#2の利点)。これが必要な場合は、個人を順番にリストする必要がある場合に備えて、個人IDの順序付き配列を別個の構造として保持することをお勧めします。利点は、同じデータセットの異なる順序で、そのような配列を複数保持できることです。

1
levik

値として名前しか持てないという制約を考えると、最初のオプションを選択します。最もクリーンで、オーバーヘッドが最小で、ルックアップが最速です。

0