Как сохранить упорядоченный объект / массив Javascript, одновременно поддерживая поиск ключей? - PullRequest
54 голосов
/ 25 апреля 2011

У меня есть некоторые данные, которые я изначально сохранил в универсальном объекте Javascript, с идентификатором в качестве ключа:

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

Однако я обнаружил, что браузеры не гарантируют определенный порядок объектов при их циклическом просмотре, поэтому в приведенном выше значении «3» предшествует «7». Я переключился на использование формата массива так:

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

Теперь я могу выполнить цикл в правильном порядке, но не могу выполнять быстрый поиск, например data["3"] без необходимости перебирать массив.

Есть ли хороший способ объединить оба подхода? Я бы предпочел не использовать отдельный объект для каждого формата, потому что объект довольно большой (сотни элементов).

1 Ответ

71 голосов
/ 25 апреля 2011

Я тоже столкнулся с этой проблемой. Решением является сохранение упорядоченного массива ключей в дополнение к исходному объекту.

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

Теперь, если вам нужен второй элемент, вы можете выполнить поиск:

var second_object = objects[order[1]];

Стандарт ECMA ничего не говорит о порядке элементов в объекте. В частности, Chrome меняет порядок клавиш, когда они выглядят как цифры. Пример:

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

если вы напечатаете это в Chrome, вы получите что-то вроде:

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

Это немного кислый .. но жизнь.

Вы также можете использовать решение Энди, связанное, в основном, объединяя эти два в один объект.

Альтернативой, которую я часто использую, является пользовательская функция карты, которая позволяет вам указать порядок, в котором перемещается объект. Как правило, вы будете выполнять сортировку, когда вы печатаете свои данные для пользователя, поэтому, пока вы создаете циклы и создаете строки таблицы (например), ваш итератор будет передавать строки в порядке, указанном вашей функцией сортировки. Я думал, что это хорошая идея:)

Подпись выглядит так:

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];
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...