Эффективность использования массивов и объектов в JavaScript
У меня есть модель, содержащая, возможно, тысячи объектов. Я хотел бы узнать, какой способ хранения и извлечения одного объекта после получения его идентификатора будет наиболее эффективным. Идентификаторы представляют собой длинные числа.
В первом варианте это простой массив с увеличивающимся индексом. Во втором варианте это ассоциативный массив и, возможно, объект, если это имеет значение. Мой вопрос заключается в том, какой из вариантов более эффективен, если мне нужно получить в основном один объект, но также иногда перебирать их и сортировать.
Первый вариант с не ассоциативным массивом:
var a = [{id: 29938, name: 'name1'},
{id: 32994, name: 'name1'}];
function getObject(id) {
for (var i=0; i < a.length; i++) {
if (a[i].id == id)
return a[i];
}
}
Второй вариант с ассоциативным массивом:
var a = []; // maybe {} makes a difference?
a[29938] = {id: 29938, name: 'name1'};
a[32994] = {id: 32994, name: 'name1'};
function getObject(id) {
return a[id];
}
Обновление:
Хорошо, я понял, что об использовании массива во втором варианте не может быть и речи. Поэтому строка объявления во втором варианте действительно должна быть: var a = {};
и вопрос только в том, что лучше работает при получении объекта с заданным id: массив или объект, где id является ключом.
и еще, изменится ли ответ, если мне придется сортировать список много раз?
Краткая версия: Массивы в основном быстрее объектов. Но 100% правильного решения не существует.
Обновление 2017 - Тест и результаты
Original Post - Explanation
В вашем вопросе есть несколько неверных формулировок.
В Javascript не существует ассоциативных массивов. Только массивы и объекты.
Это массивы:.
Это тоже массив:
По сути, это массив с дырками, потому что каждый массив имеет непрерывную индексацию. Это медленнее, чем массивы без дыр. Но итерация вручную по массиву еще медленнее (в основном).
Это объект:.
Вот тест производительности трех возможностей:
Lookup Array vs Holey Array vs Object Performance Test
Отличная статья на эту тему в Smashing Magazine: Writing fast memory efficient JavaScript
Это не совсем вопрос производительности, поскольку массивы и объекты работают совершенно по-разному (или, по крайней мере, должны работать). Массивы имеют непрерывный индекс
0...n
, в то время как объекты отображают произвольные ключи на произвольные значения. Если вы хотите предоставить конкретные ключи, то единственным выбором будет объект. Если же ключи вам не важны, то это массив.Если попытаться задать массиву произвольные (числовые) ключи, то это действительно приведет к потере производительности, поскольку поведенчески массив будет заполнять все промежуточные индексы:
(Обратите внимание, что массив не фактически содержит 99
неопределенных
значений, но он будет вести себя так, поскольку вы [предположительно] итерируете массив в какой-то момент.)Литералы для обеих опций должны наглядно показать, как их можно использовать:
С ЕС6 наиболее производительный способ заключается в использовании карта.
Вы можете использовать сегодня возможности ES6 с помощью ШИМ (https://github.com/es-shims/es6-shim).
Производительность может изменяться в зависимости от браузера и сценарий. Но вот один из примеров, где "карта" является самым производительным: https://jsperf.com/es6-map-vs-object-properties/2
Ссылка https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Map
В NodeJS если вы знаете
идентификатор
, цикл через массив идет очень медленно по сравнению собъекта[идентификатор]
.Я попытался перейти в следующее измерение, в буквальном смысле этого слова.
Если задан двумерный массив, в котором оси x и y всегда имеют одинаковую длину, то быстрее ли будет:
a) найти ячейку, создав двумерный массив и найдя первый индекс, а затем второй индекс, т.е:
или
б) создать объект со строковым представлением координат x и y, а затем выполнить единственный поиск по этому obj, т.е:
Результат: Оказалось, что гораздо быстрее выполнить два поиска числовых индексов в массивах, чем один поиск свойств в объекте.
Результаты здесь:
http://jsperf.com/arr-vs-obj-lookup-2
Это зависит от использования. Если дело объекты поиска-это очень быстрее.
Вот пример Plunker для тестирования производительности массива и объекта поиска.
https://plnkr.co/edit/n2expPWVmsdR3zmXvX4C?p=preview
Вы увидите, что; Глядя на 5.000 элементы 5.000 длина массива коллекции, захватить
3000
miliseconsОднако, глядя на 5.000 элементы в объект 5.000 свойства, берут только
2
или3
miliseconsТакже делает объект "Дерево" Дон'т сделать огромную разницу
У меня была похожая проблема, что я столкнулся, когда мне нужно сохранить видео подсвечники из источника событий ограничивается х предметов. Я мог бы их положить в объект, где время каждая свеча будет действовать в качестве ключа, а сама свеча будет действовать в качестве значения. Другая возможность заключается в том, что я могу хранить его в массив, где каждый элемент был сам свечи. Одна проблема о прямых свечей заключается в том, что они продолжают присылать обновления на ту же отметку времени, где последнее обновление содержит самые последние данные, поэтому вы либо обновить существующий элемент или добавить новый. Так вот это хороший ориентир, который пытается объединить все 3 возможности. Массивы в растворе ниже приведены хотяб 4 раза быстрее в среднем. Не стесняйтесь играть
Заключение 10 это предел здесь
Если у вас есть отсортированный массив, то вы можете сделать бинарный поиск, и это намного быстрее, чем поиск объекта, вы можете посмотреть мой ответ здесь: https://stackoverflow.com/questions/57422718/how-to-search-faster-in-a-sorted-array-using-javascript