Объекты против массивов в Javascript для пар ключ / значение - PullRequest
78 голосов
/ 27 марта 2009

Скажем, у вас очень простая структура данных:

(personId, name)

... и вы хотите сохранить некоторые из них в переменной javascript. На мой взгляд, у вас есть три варианта:

// 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'}
};

Второй или третий вариант - это, очевидно, правильный путь, если у вас есть (или вы ожидаете, что у вас может быть) более одной «ценностной» части для хранения (например, добавление их возраста или чего-то такого), поэтому аргумента, давайте предположим, что в этой структуре никогда не будет больше значений данных, необходимых. Какой из них вы выбираете и почему?


Редактировать : в примере теперь показана наиболее распространенная ситуация: непоследовательные идентификаторы.

Ответы [ 6 ]

57 голосов
/ 27 марта 2009

Каждое решение имеет свои варианты использования.

Я думаю, что первое решение хорошо, если вы пытаетесь определить отношение «один к одному» (например, простое отображение), особенно если вам нужно использовать ключ в качестве ключа поиска.

Второе решение кажется мне наиболее надежным в целом, и я, вероятно, воспользуюсь им, если мне не понадобится клавиша быстрого поиска:

  • Это самоописание, так что вы не должен зависеть от того, кто использует человек чтобы знать, что ключ является идентификатором пользователя.
  • Каждый объект приходит в себя, что лучше для передачи данных в другом месте - вместо двух параметров (имя и фамилия) вы просто раздаетесь человек.
  • Это редкая проблема, но иногда значения ключа могут быть недействительными для использовать в качестве ключей. Например, я однажды хотел отобразить преобразования строк (например, ":" до ">"), но так как ":" неверное имя переменной мне пришлось используйте второй метод.
  • Это легко расширяется, на случай, если где-то вдоль линии вам нужно добавить больше данных для некоторых (или всех) пользователей. (Извините, я знаю о вашем "для ради аргумента ", но это важный аспект.)

Третий вариант был бы хорош, если вам нужно быстрое время поиска + некоторые из перечисленных выше преимуществ (передача данных, самоописание). Однако, если вам не нужно быстрое время поиска, это гораздо более громоздко. Кроме того, в любом случае вы рискуете ошибиться, если идентификатор в объекте каким-либо образом отличается от идентификатора в people .

7 голосов
/ 27 марта 2009

На самом деле существует четвертый вариант:

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

, поскольку ваши значения оказываются последовательными. (Конечно, вам придется добавить / вычесть один --- или просто положить undefined в качестве первого элемента).

Лично я бы пошел с вашим (1) или (3), потому что они будут быстрее всего искать кого-то по идентификатору (O log n в худшем случае). Если вам нужно найти идентификатор 3 в (2), вы можете найти его по индексу (в этом случае my (4) в порядке) или искать - O (n).

Пояснение: я говорю, что O (log n ) - худший результат, потому что, AFAIK, и реализация может принять решение использовать сбалансированное дерево вместо хеш-таблицы. Хеш-таблица была бы O (1), предполагая минимальные коллизии.

Редактировать с nickf: с тех пор я изменил пример в ОП, поэтому этот ответ может не иметь такого большого смысла. Извинения.

после редактирования

Хорошо, постредактируйте, я бы выбрал вариант (3). Это расширяемый (легко добавлять новые атрибуты), функции быстрого поиска, а также может быть повторен. Он также позволяет вам перейти от ввода обратно к ID, если вам нужно.

Опция (1) будет полезна, если (а) вам нужно сэкономить память; (б) вам никогда не нужно переходить от объекта обратно к идентификатору; (c) вы никогда не будете расширять хранимые данные (например, вы не можете добавить фамилию человека)

Вариант (2) хорош, если вам (а) необходимо сохранить порядок; (б) нужно перебрать все элементы; (c) не нужно искать элементы по id, если они не отсортированы по id (вы можете выполнить бинарный поиск в O (log n ). Обратите внимание, конечно, если вам нужно сохранить его отсортировано, тогда вы заплатите за вставку.

2 голосов
/ 03 октября 2011

Я создал небольшую библиотеку для управления парами ключ-значение.

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

Используется

  • объект для хранения ключей, который позволяет быстро удалять и извлекать значения операции и
  • связанный список, обеспечивающий действительно быструю итерацию значения

Надеюсь, это поможет:)

2 голосов
/ 27 марта 2009

Предполагая, что данные никогда не изменятся, первый (единственный объект) вариант является лучшим.

Простота структуры означает, что ее анализировать быстрее всего, и в случае небольших, редко (или никогда) изменяющихся наборов данных, таких как этот, я могу только представить, что он будет часто выполняться - в этом случае минимальный накладные расходы - путь.

1 голос
/ 27 марта 2009

Третий вариант является лучшим для любого перспективного приложения. Возможно, вы захотите добавить больше полей в вашу личную запись, поэтому первый вариант не подходит. Кроме того, весьма вероятно, что у вас будет большое количество людей для хранения, и вы захотите быстро просмотреть записи - таким образом, выгрузка их в простой массив (как это делается в варианте № 2) также не является хорошей идеей.

Третий шаблон дает вам возможность использовать любую строку в качестве идентификатора, иметь сложные структуры Person и получать и устанавливать записи о персонале в постоянное время. Это определенно путь.

Единственное, чего не хватает в варианте №3, - это стабильный детерминированный порядок (что является преимуществом варианта №2). Если вам это нужно, я бы порекомендовал хранить упорядоченный массив идентификаторов лиц в качестве отдельной структуры, когда вам нужно составить список людей по порядку. Преимущество состоит в том, что вы можете хранить несколько таких массивов для разных порядков одного и того же набора данных.

0 голосов
/ 27 марта 2009

Учитывая ваше ограничение, что у вас будет только имя в качестве значения, я бы выбрал первый вариант. Это самый чистый, с наименьшими накладными расходами и самый быстрый поиск.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...