Как легко разбить массив на куски одинакового размера в Javascript

В этой статье вы научитесь разбивать массив Javascript на куски с указанным размером, используя разные реализации.

1. Использование цикла for и функции слайса

По сути, каждый метод будет использовать метод slice для разделения массива, в этом случае отличает этот метод цикл for.

В случае, если массив не является однородным, остальные элементы также будут в массиве, однако по очевидным причинам размер будет меньше.

/**
* Returns an array with arrays of the given size.
*
* @param myArray {Array} array to split
* @param chunk_size {Integer} Size of every group
*/
function chunkArray(myArray, chunk_size){
var index = 0;
var arrayLength = myArray.length;
var tempArray = [];
for (index = 0; index < arrayLength; index += chunk_size) {
myChunk = myArray.slice(index, index+chunk_size);
// Do something if you want with the group
tempArray.push(myChunk);
}
return tempArray;
}
// Split in group of 3 items
var result = chunkArray([1,2,3,4,5,6,7,8], 3);
// Outputs : [ [1,2,3] , [4,5,6] ,[7,8] ]
console.log(result);

2. Использование цикла for, слайса и функции set в прототипе массива

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

/**
* Define the chunk method in the prototype of an array
* that returns an array with arrays of the given size.
*
* @param chunkSize {Integer} Size of every group
*/
Object.defineProperty(Array.prototype, 'chunk', {
value: function(chunkSize){
var temporal = [];
for (var i = 0; i < this.length; i+= chunkSize){
temporal.push(this.slice(i,i+chunkSize));
}
return temporal;
}
});
// Split in group of 3 items
var result = [1,2,3,4,5,6,7,8].chunk(3);
// Outputs : [ [1,2,3] , [4,5,6] ,[7,8] ]
console.log(result);

Как видите, принцип тот же - использование цикла for и функции slice, но вместо того, чтобы использовать его в функции, он регистрируется в прототипе массива.

3. Использование карты массива в прототипе массива

map Функция вызывает предоставленную функцию обратного вызова один раз для каждого элемента в массиве по порядку и создает новый массив из результатов. Функция вернет массив с длиной, определяемой делением длины предоставленного массива на размер фрагмента. Функция fill (в качестве параметра не указано) будет заполнять созданный массив неопределенным, и, наконец, каждое неопределенное значение в массиве будет заменено новым массивом (результат среза выделенного массива с соответствующим индексом).

/**
* Define the chunk method in the prototype of an array
* that returns an array with arrays of the given size.
*
* @param chunkSize {Integer} Size of every group
*/
Object.defineProperty(Array.prototype, 'chunk', {
value: function(chunkSize) {
var that = this;
return Array(Math.ceil(that.length/chunkSize)).fill().map(function(_,i){
return that.slice(i*chunkSize,i*chunkSize+chunkSize);
});
}
});
// Split in group of 3 items
var result = [1,2,3,4,5,6,7,8].chunk(3);
// Outputs : [ [1,2,3] , [4,5,6] ,[7,8] ]
console.log(result);

4. Использование цикла и среза

В типичных и нормальных условиях цикл while немного быстрее. Тем не менее, мы должны знать, что этот прирост производительности важен для большого количества итераций. Поэтому, если ваш массив огромен, и вы хотите разбить его на куски с небольшим числом, вы должны рассмотреть использование метода, который использует while, чтобы значительно увеличить производительность.

/**
* Returns an array with arrays of the given size.
*
* @param myArray {Array} Array to split
* @param chunkSize {Integer} Size of every group
*/
function chunkArray(myArray, chunk_size){
var results = [];
while (myArray.length) {
results.push(myArray.splice(0, chunk_size));
}
return results;
}
// Split in group of 3 items
var result = chunkArray([1,2,3,4,5,6,7,8], 3);
// Outputs : [ [1,2,3] , [4,5,6] ,[7,8] ]
console.log(result);

5. Использование slice и concat в рекурсивной функции

В этом методе рекурсия довольно дорогая, если говорить о производительности и ресурсах браузера. Кроме того, concat Функция в некоторых браузерах значительно медленнее, чем join метод.

/**
* Define the chunk method in the prototype of an array
* that returns an array with arrays of the given size (with a recursive function).
*
* @param chunk_size {Integer} Size of every group
*/
Array.prototype.chunk = function (chunk_size) {
if ( !this.length ) {
return [];
}
return [ this.slice( 0, chunk_size ) ].concat(this.slice(chunk_size).chunk(chunk_size));
};

Отказ от ответственности: не используйте в производственных средах с огромным количеством данных.

О производительности

Нашим простым тестом будет разделение массива из 100 000 (100 КБ) элементов (только цифры) на куски по 3 элемента / массива. Эта задача будет выполнена 1000 (1K) раз, чтобы обеспечить высокую точность, значения даны в миллисекундах.

Тест был выполнен на машине со следующими характеристиками:

  • Операционная система Windows 10 Pro 64-битная
  • Chrome 53.0.2785.116 м (64 бит)
  • Процессор Intel® Core i5-4590 с тактовой частотой 3,30 ГГц (4 процессора), ~ 3,3 ГГц
  • 8192 МБ ОЗУ
метод
Общее время (мс)
Среднее время на задачу (мс)
1 (для цикла)+5778,015000000001+5,776805000000013
2 (для цикла в прототипе)5681.145+5,679875000000007
3 (карта массива в прототипе)+8855,470000000001+8,854190000000001
4 (пока цикл)+1468,6650000000002+1,468275000000002
5 (рекурсивная функция со срезом и конкатом)ТЕСТ-АварииТЕСТ-Аварии
  • Цикл while кажется самым быстрым способом разделения массива на части с высокой производительностью по сравнению с другими.
  • В тесте следует отметить одну деталь: чем больше элементов в каждом чанке, тем быстрее выполняется задача.
  • При использовании метода № 5 происходит сбой браузера, поэтому использование этого метода не рекомендуется для большого количества данных.

Повеселись !

Ссылка на основную публикацию
Adblock
detector