Объекты против массивов в JavaScript для пар ключ/значение
скажем, у вас очень простая структура данных:
(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'}
};
второй или третий вариант-это, очевидно, путь, если у вас есть (или ожидаете, что у вас может быть) более одной части "значения" для хранения (например, добавление в их возрасте или что-то еще), поэтому, ради аргумента, давайте предположим, что никогда больше не будет никаких значений данных, необходимых в эта структура. Какой из них вы выберете и почему?
Edit: пример теперь показывает наиболее распространенную ситуацию: не последовательные идентификаторы.
6 ответов:
каждое решение имеет свои варианты использования.
Я думаю, что первое решение хорошо, если вы пытаетесь определить отношение "один к одному" (например, простое сопоставление), особенно если вам нужно использовать ключ в качестве ключа поиска.
второе решение кажется мне самым надежным в целом, и я бы, вероятно, использовал его, если бы мне не нужен был быстрый ключ поиска:
- это самоописание, так что вам не должны зависеть от тех, кто использует человек чтобы знать, что ключ-это идентификатор пользователя.
- каждый объект самодостаточный, что лучше для передачи данных в другом месте - вместо двух параметров (id и имя) вы просто проходите вокруг люди.
- это редкая проблема, но иногда значения ключа могут быть недопустимы для использовать в качестве ключей. Например, я однажды требуется сопоставить преобразования строк (например,": "to">"), но поскольку ":" не является ли допустимым именем переменной, которое я должен был используйте второй способ.
- он легко расширяется, в случай где-то вдоль линии вы должны добавьте дополнительные данные для некоторых (или всех) пользователей. (Извините, я знаю о вашем "for аргумент" но это важный аспект.)
третье было бы хорошо, если вам нужно быстрое время поиска + некоторые из преимуществ, перечисленных выше (передача данных вокруг, самоописание). Однако, если вам не нужно быстрое время поиска, это намного сложнее. Кроме того, в любом случае вы рискуете ошибиться, если идентификатор в объекте каким-то образом отличается от id в человек.
на самом деле, есть четвертый вариант:
var people = ['Joe', 'Sam', 'Eve'];
так как ваши значения оказываются последовательными. (Конечно, вам придется добавить/вычесть один --- или просто поставить undefined в качестве первого элемента).
лично я бы пошел с вашим (1) или (3), потому что они будут быстрее всего искать кого-то по ID (O logn в худшем случае). Если вам нужно найти id 3 в (2), Вы можете либо найти его по индексу (в этом случае мой (4) в порядке), либо вам нужно выполнить поиск - O (n).
уточнение: я говорю O (logn) это худшее, что может быть, потому что, AFAIK, и реализация может решить использовать сбалансированное дерево вместо хэш-таблицы. Хэш-таблица будет O (1), предполагая минимальные коллизии.
Edit from nickf: с тех пор я изменил пример в OP, поэтому этот ответ может больше не иметь смысла. Извинения.
редактировать
ОК, после редактирования, я бы выбрал вариант (3). Это расширяемый (легко добавлять новые атрибуты), функции быстрого поиска, а также может быть повторен. Он также позволяет перейти от входа обратно к идентификатору, если вам это нужно.
Вариант (1) был бы полезен, если (А) вам нужно сохранить память; (б) вам никогда не нужно переходить от объекта обратно к идентификатору; (в) вы никогда не будете расширять сохраненные данные (например, вы не можете добавить фамилию человека)
Вариант (2) хорош, если вам (а) нужно сохранить порядок; (Б) нужно перебирать все элементы; (в) не нужно для поиска элементов по id, если он не отсортирован по id (вы можете выполнить двоичный поиск в O (logn). Обратите внимание, конечно, если вам нужно сохранить его сортировку, то вы будете платить стоимость на insert.
Я создал небольшую библиотеку для управления пар ключ / значение.
https://github.com/scaraveos/keyval.js#readme
Он использует
- объект для хранения ключей, который позволяет быстро удалять и извлекать значения операции и
- связанный список, чтобы обеспечить действительно быстрое значение итерации
надеюсь, что это помогает :)
третий вариант является лучшим для любого перспективного приложения. Вероятно, вы захотите добавить больше полей в свою личную запись, поэтому первый вариант непригоден. Кроме того, очень вероятно, что у вас будет большое количество людей для хранения, и вы захотите быстро искать записи - таким образом, сбрасывать их в простой массив (как это делается в Варианте № 2) тоже не очень хорошая идея.
третий шаблон дает вам возможность использовать любую строку в качестве идентификатора, имеют сложный человек структуры и получить и установить записи человека в постоянное время. Это определенно правильный путь.
одна вещь, которой не хватает варианту № 3, - это стабильный детерминированный порядок (что является преимуществом варианта № 2). Если вам это нужно, я бы рекомендовал сохранить упорядоченный массив идентификаторов лиц в качестве отдельной структуры, когда вам нужно перечислить людей по порядку. Преимущество будет заключаться в том, что вы можете хранить несколько таких массивов для разных порядков одного и того же набора данных.