Поиск по массиву объектов
Есть массив объектов. Я знаю ключ к нужному объекту(key=137),но не знаю который это объект в массиве(нужно раза 3 прочитать чтобы понять суть). Можно запустить перебор всего массива,но это долго(это для всплывающего окна пользователя). Иначе окно будет всплывать вечность. Как выбрать объект из массива, зная его ключ. Скрин прилагается:
![]() |
key это значение свойства объекта, он к массиву слабо относится
думаю придётся все перебирать |
ну если массив упорядоченный по номеру то очень просто)
Даже если key не соответсвует номеру массива в упорядоченном массиве можно использовать алгоритм бинарного поиска Можете упорядочить массив и будет вам счастье. Упорядочевать массив врятли придется часто, так что там тормоза не критичны |
Кстати если так нужно часто искать метку то почему бы не поменять формат? Сделать асоциативный массив по ключам. Или если не жалко память то можно сделать карту массива что обеспечит мгновенный поиск.
Карта массива: var arr = [ { key: 1, label: "trololo1" }, { key: 2, label: "trololo2" } ]; var map = { 1: 0, 2: 1 }; alert(arr[map[1]].label); Естественно что карта должна генерироваться налету, но идея должна быть понятна. |
может быть Array.prototype.filter
будет быстро искать? var arr = [ {key: 3, label: '333333333'}, {key: 137, label: '555'}, {key: 2, label: '222222'} ], myArr = arr.filter(function (item) { return (item.key === 137); }); alert(JSON.stringify(myArr)); |
Pavel M., мечтай.)
|
Pavel M.,
Если уж нужен 1 элемент и использовать нативные методы то надо пользовать some, потому что его можно остановить найдя нужный элемент, а filter пройдет весь массив целиком. |
tsigel, в ff есть ещё find:) :
var arr = [ {key: 3, label: '333333333'}, {key: 137, label: '555'}, {key: 2, label: '222222'} ], myArr = arr.find(el => el.key === 137); alert(JSON.stringify(myArr));но цикл всё равно быстрее.) |
Aetae,
Цикл for быстрее чем some? то есть var arr = [...]; var someKey = "somekey" for (var i=0,l=arr.length;i<l;i++) { if (arr[i].key==someKey) { //... break; } } быстрее чем var arr = [...]; var someKey = "somekey" arr.some(function (el) { if (el.key==someKey) { //... return true; } }); Вроде бы писали везде что эти нативные методы не уступают обычным переборам. Точнее я читал что они иногда даже быстрее, а иногда - медленнее, но не значительно. |
<script src="http://sugarjs.com/release/current/sugar-full.min.js"></script> <script> var arr = [ {key: 3, label: '333333333'}, {key: 137, label: '555'}, {key: 2, label: '222222'} ]; alert(JSON.stringify(arr.find({key: 137}))); </script> |
Цитата:
*** А по теме: Collection Работает быстрее итераторов, циклов и всех известных библиотек и со всеми возможными типами данных :) |
действительно
попробовал скорость filter и обычного цикла на большом массиве в Хроме, FF, IE11 у меня цикл быстрее в разы (см. в console) спасибо Aetae - не знал var i, maxItems = 1e6, arr = [], needKey = 500137, // где-то в середине myArr; // генерим массив for (i = 0; i < maxItems; i += 1) { arr.push({key: i, label: i + ''}); } // test filter console.time('filter'); myArr = arr.filter(function (item) { return (item.key === needKey); }); console.timeEnd('filter'); alert(JSON.stringify(myArr)); // test цикл myArr = []; console.time('for'); for (i = 0; i < arr.length; i += 1) { if (arr[i].key === needKey) { myArr.push(arr[i]); break; } } console.timeEnd('for'); alert(JSON.stringify(myArr)); |
Pavel M. никогда не делай бенчмарки через консоль отладчика, т.к. он отключает использование JIT компилятора и результат замеров может значительно отличаться.
|
Цитата:
var i, maxItems = 1e6, arr = [], needKey = 500137, // где-то в середине myArr; // генерим массив for (i = 0; i < maxItems; i += 1) { arr.push({key: i, label: i + ''}); } // test filter console.time('some'); myArr = []; arr.some(function (item) { if (item.key === needKey) { myArr = [item]; return true; } return false; }); console.timeEnd('some'); alert(JSON.stringify(myArr)); // test цикл myArr = []; console.time('for'); for (i = 0; i < arr.length; i += 1) { if (arr[i].key === needKey) { myArr.push(arr[i]); break; } } console.timeEnd('for'); alert(JSON.stringify(myArr)); some у меня отрабатывает в полтора раза быстрее filter, но все еще в два раза медленнее, чем for: Цитата:
|
Цитата:
|
Цитата:
Для тестирования именно скорости итераций лучше самом написать простой тест, как например тут https://github.com/kobezzza/Collecti...ter/benchmarks Цитата:
Я уже молчу про то, что нативные интерфейсы алгоритмически убоги и работают только с массивами. Очень частый пример, нужно сделать фильтр, потом мап, а потом взять первые 10 результатов, т.е. filter().map().slice() Алгоритмическая сложность просто ужасна, думаю всем это понятно. Гораздо лучше сделать: map(..., {filter(), slice()}) Т.е. всё в один проход вместо 3-х |
Цитата:
Цитата:
|
Цитата:
С использованием либы Collection это будет выглядеть так: $C(/* тут наш объект для итераций */).map(function () { ... }, { filter: function () { ... }, from: 100, count: 10 }); Цитата:
|
Цитата:
|
kobezzza,
Ну это потому что ты написал эту либу))) Я тоже таскаю некоторые свои штуки из проекта в проект) А подключать либу на 17кб просто чтобы не париться - неохота) Я и так не парюсь) |
Цитата:
результат почти тот же в Хроме, FF var timeStart, i, maxItems = 1e6, arr = [], needKey = 500137, // где-то в середине myArr; // генерим массив for (i = 0; i < maxItems; i += 1) { arr.push({key: i, label: i + ''}); } // test filter timeStart = +(new Date()); myArr = arr.filter(function (item) { return (item.key === needKey); }); alert('filter ms: ' + (new Date() - timeStart)); // test цикл myArr = []; timeStart = +(new Date()); for (i = 0; i < arr.length; i += 1) { if (arr[i].key === needKey) { myArr.push(arr[i]); break; } } alert('for ms: ' + (new Date() - timeStart)); |
Цитата:
Цитата:
|
Pavel M.,
Ваш тест алгоритмически не верен. Фильт проходит весь массив а фор - часть. Хотите такой тест сравнивайте с some |
Цитата:
Цитата:
|
Цитата:
|
Часовой пояс GMT +3, время: 02:01. |