Задать вопрос
@soofftt91

Как на JS создать цикл для неупорядоченного массива?

Имеется массив следующего вида:
var arr = [
    20: "",
    1213: "",
    414212: "",
    ......
    341156243: ""
];

Мне нужно создать цикл который пройдётся по всем существующим в массиве "элементам" и выведет их в консоль. Основная сложность в том что элементов может быть до 10 млн.

------------------
Когда элементов до 1 млн. задачу решал следующим образом:
Object.keys(arr).forEach(function (key) {
    console.log(key);
});

Но при большем кол-ве объектов функция Object.keys(arr) выполняется слишком долго и браузеры либо "убивают" вкладку, либо спрашивают у пользователя хочет он остановить выполнение скрипта или нет.

Т.е. нужно выполнить Object.keys(arr) в несколько этапов либо создать цикл в котором можно получать "key".

P.S. на самом дела данные конечно не будут выводится в консоль, это исключительно для примера.
  • Вопрос задан
  • 471 просмотр
Подписаться 1 Оценить 4 комментария
Решения вопроса 1
@Interface
Ну тут напрашивается обычный цикл for (key in array){...}

UPDATE
:
Если вам действительно нужно обрабатывать огромные разреженные массивы на javascript и подвешивать процесс не желательно (что на самом то деле надо избегать вообще), то можно попробовать делать это асинхронно как писали Константин Отпущенников и evg_ (однако они не предложили как можно итерировать объект асинхронно, а нам нужна итерация именно объекта, а не массива в данном случае). Так вот я нашел одно решение, оно довольно.. кхм.. специфическое, если придумаете способ лучше - пишите. Проблема в том, что мы можем перебрать часть свойств мегообъекта и break'нуться из цикла, но мы не сможем вернуться в то же место, поэтому надо как-то добиться запоминания состояния цикла... и единственное, что я нашел - это удалять элементы первоначального объекта (их можно и восстановить в другой, но вы это можете добавить сами если будет нужно).
Особенности метода:
- изменение изначального объекта;
- скорость просядет на порядки (без преувеличений, у меня этот способ оказался в 200 - 400 раз медленее);
- зато можно не вешать всю страницу;
- выбирать порцию данных за один проход (чем больше, тем медленнее алгоритм для одной части (больше тормозов на странице), за то быстрее обработка в целом);
- можно повесить прогресс бар, отображающий прогресс итерации;

Код:
var arr = [];
for (var i = 0; i < 100 * 1000; i++){
	arr.push(i);
};

function bench(name, fn){
	var startTime = performance.now();
	var res = fn();
	var finishTime = performance.now();
	console.log(name + ' took: ', finishTime - startTime);
	return res;
};

bench('get keys', ()=>
	Object.keys(arr) // ~670 ms
);

// --------------

function getKeyValAsync(bigObject, limit, cb){
	var result = [];

	function getPart(){
		var doneAmount = 0;
		for (var i in bigObject){
			if (!bigObject.hasOwnProperty(i)){
				continue;
			};
			result.push({
				key: i,
				val: bigObject[i]
			});			
			delete bigObject[i];
			doneAmount++;
			if (doneAmount > limit){
				setTimeout(() => bench('part: ', getPart), 10);
				return;
			};
		};
		cb(result);		
	};

	getPart();
};

var keyValPairs;
var start = performance.now();
getKeyValAsync(arr, 10000, res => {
	keyValPairs = res;
	console.log('By parts time: ' + (performance.now() - start));
});
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
@WQP
Разбивайте массив на части array_chunk
Ответ написан
Комментировать
Я предлагаю Вам использовать асинхронность. А именно setTimeout() с минимальной задержкой (можно писать 0, браузер все равно выполнит задержку) - это позволит не блочить другой полезный синхронный код.
Другая беда в том, что если у вас на странице есть различные обработчики событий, то они будут ждать выполнентя асинхронного вывода - тут уже надо подумать и действительно посмотреть в сторону деление массива на части.
Ответ написан
evgeniy8705
@evgeniy8705
Повелитель вселенной
Массив в JS как раз таки имеет упорядоченную структуру.
Для таких целей лучше использовать объекты.
А для перебора 100500 элементов использовать setTimeout
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы