Разделить массив на части
Описание проблемы:
У меня есть массив JavaScript следующего вида:
["Element 1", "Element 2", "Element 3", ...]; // около ста элементов
Какой подход будет уместен для разделения (чункования) этого массива на множество меньших массивов, каждый из которых содержит не более 10 элементов?
5 ответ(ов)
Вот версия на ES6, использующая метод reduce
для дробления массива на чанки:
const perChunk = 2; // количество элементов в чанке
const inputArray = ['a', 'b', 'c', 'd', 'e'];
const result = inputArray.reduce((resultArray, item, index) => {
const chunkIndex = Math.floor(index / perChunk);
if (!resultArray[chunkIndex]) {
resultArray[chunkIndex] = []; // начинаем новый чанк
}
resultArray[chunkIndex].push(item);
return resultArray;
}, []);
console.log(result); // результат: [['a','b'], ['c','d'], ['e']]
Массив inputArray
остается неизменным, и вы можете легко увеличивать функциональность, добавляя цепочку других методов map
или reduce
.
Если вы предпочитаете более короткий, но менее читаемый вариант, можно использовать concat
, чтобы добиться того же результата:
inputArray.reduce((all, one, i) => {
const ch = Math.floor(i / perChunk);
all[ch] = [].concat((all[ch] || []), one);
return all;
}, []);
Также можно использовать оператор остатка, чтобы помещать последовательные элементы в разные чанки:
const ch = (i % perChunk);
Таким образом, есть несколько подходов к решению этой задачи в JavaScript.
Чтобы разбить массив на чанки размером n
с использованием генераторов в JavaScript, вы можете использовать следующий код:
function* chunks(arr, n) {
for (let i = 0; i < arr.length; i += n) {
yield arr.slice(i, i + n);
}
}
let someArray = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log([...chunks(someArray, 2)]); // [[0, 1], [2, 3], [4, 5], [6, 7], [8, 9]]
Этот код определяет функцию-генератор chunks
, которая принимает массив и размер чанка, возвращая генератор, который производит подмассивы.
Для использования с TypeScript можно добавить типизацию следующим образом:
function* chunks<T>(arr: T[], n: number): Generator<T[], void> {
for (let i = 0; i < arr.length; i += n) {
yield arr.slice(i, i + n);
}
}
Здесь мы добавили дженерик <T>
, который позволяет функции работать с массивами любого типа. Таким образом, вы получите типизированный генератор, возвращающий подмассивы заданного типа T
.
Для того чтобы разделить массив на части с использованием ES6, можно воспользоваться методом splice()
в сочетании с учетом размера чанка. Вот как это можно сделать:
let [list, chunkSize] = [[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], 6];
list = [...Array(Math.ceil(list.length / chunkSize))].map(_ => list.splice(0, chunkSize));
console.log(list);
В этом коде мы сначала вычисляем, сколько частей нам нужно, используя Math.ceil(list.length / chunkSize)
, чтобы получить округленное вверх значение. Затем мы создаем новый массив, состоящий из этих частей, где каждый элемент — это результат выполнения list.splice(0, chunkSize)
, который извлекает chunkSize
элементов из оригинального массива list
.
В результате, console.log(list)
выведет массив массивов, где каждый подмассив содержит элементы оригинального массива размером не больше заданного chunkSize
.
Замечание: Использование splice
модифицирует исходный массив list
, поэтому если вам нужно сохранить его в неизменном виде, лучше использовать фильтрацию или другие методы, такие как slice
.
Я протестировал различные варианты на jsperf.com. Результаты доступны по следующей ссылке: https://web.archive.org/web/20150909134228/https://jsperf.com/chunk-mtds.
Самая быстрая функция (которая также работает с IE8) выглядит следующим образом:
function chunk(arr, chunkSize) {
if (chunkSize <= 0) throw "Invalid chunk size";
var R = [];
for (var i=0,len=arr.length; i<len; i+=chunkSize)
R.push(arr.slice(i,i+chunkSize));
return R;
}
Также стоит отметить, что функция может выдавать ошибку, если размер чанка не положителен.
В настоящее время вы можете использовать функцию chunk
из библиотеки Lodash, чтобы разбить массив на более мелкие массивы. Документацию можно найти по следующей ссылке: https://lodash.com/docs#chunk. Больше нет необходимости заморачиваться с циклами!
Как перемешать (сделать случайным) массив в JavaScript?
Как объединить два массива в JavaScript и удалить дубликаты?
Как очистить массив в JavaScript?
Как удалить все дубликаты из массива объектов?
Как преобразовать строку, разделённую запятыми, в массив?