web-dev-qa-db-ja.com

キー検索も維持しながら、Javascriptオブジェクト/配列を順序付けする方法は?

IDをキーとして、最初に汎用Javascriptオブジェクトに保存したデータがいくつかあります。

{
  "7": {"id":"7","name":"Hello"},
  "3": {"id":"3","name":"World"},
  ...
}

ただし、ブラウザはループ処理時に特定のオブジェクトの順序を保証しないため、上記の「3」は「7」よりも前になります。このような配列形式を使用するように切り替えました。

[
  {"id":"7","name":"Hello"},
  {"id":"3","name":"World"},
  ...
]

これで、正しい順序でループできますが、高速検索を実行できません。 data["3"]配列をループする必要なし。

両方のアプローチを組み合わせる良い方法はありますか?オブジェクトは非常に大きい(数百の要素)ため、各形式に個別のオブジェクトを使用することは避けたいです。

54
DisgruntledGoat

私もこの問題に出くわしました。解決策は、元のオブジェクトに加えて、キーの順序付き配列を保持することです。

var objects = {
  "7": {"id":"7","name":"Hello"},
  "3": {"id":"3","name":"World"},
  ...
}
var order = [ "3", "7", ... ];

2番目の要素が必要な場合は、このルックアップを実行できます。

var second_object = objects[order[1]];

ECMA標準では、オブジェクト内の要素の順序については何も言及されていません。そして、具体的にはChromeはキーがlike likeの場合にキーを並べ替えます。例:

var example = {
    "a": "a",
    "b": "b",
    "1": "1",
    "2": "2"
};

これをChromeで印刷すると、次のようになります。

{
    1: "1",
    2: "2",
    "a": "a",
    "b": "b"
};

それは少し酸っぱい..しかし人生です。

同様に、Andyがリンクしたソリューションを使用して、基本的にこれら2つを1つのオブジェクトにラップすることができます。

私がよく使用する代替方法は、オブジェクトを走査する順序を指定できるカスタムマップ関数です。通常、ユーザーにデータを出力するときに並べ替えを行うため、テーブル行をループして作成している間(たとえば)、イテレーターは並べ替え関数で指定した順序で行を渡します。いいアイデアだと思いました:)

署名は次のようになります。

function map(object, callback, sort_function);

使用例:

map(object, function (row) {
   table.add_row(row.header, row.value);
}, function (key1, key2) {
   return object[key1] - object[key2];
});
73
Halcyon