Мне нужно разбить массив JavaScript на n
куски определенного размера.
Например: учитывая этот массив
["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"]
и a n
равно 4, результат должен быть таким:
[ ["a1", "a2", "a3", "a4"],
["a5", "a6", "a7", "a8"],
["a9", "a10", "a11", "a12"],
["a13"]
]
Мне известны решения этой проблемы на чистом JavaScript , но, поскольку я уже использую Lodash, мне интересно, предоставляет ли Lodash лучшее решение для этой проблемы.
Редактировать:
Я создал тест jsPerf, чтобы проверить, насколько медленнее решение для подчеркивания.
javascript
split
functional-programming
underscore.js
lodash
Сезар Канасса
источник
источник
Для решения на основе Underscore попробуйте следующее:
var data = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"]; var n = 3; var lists = _.groupBy(data, function(element, index){ return Math.floor(index/n); }); lists = _.toArray(lists); //Added this to convert the returned object to an array. console.log(lists);
Используя метод цепной оболочки, вы можете объединить два оператора, как показано ниже:
var data = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"]; var n = 3; var lists = _.chain(data).groupBy(function(element, index){ return Math.floor(index/n); }).toArray() .value();
источник
groupBy
возвращает объект , а не массив. Это не нарушитель договоренностей - вы получаете в основном те же функции, но немного странной семантики. Изменить: О, он делает это для поддержания цепочки. Все еще интересно.splice
цикл по-прежнему является трехстрочным и, как я предполагаю, намного более производительным. Если ваши массивы короткие, это, вероятно, не имеет значения, но если вы имеете дело с сотнями или тысячами элементов, следите за их производительностью.Возможно более простое выражение:
const coll = [ "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9" ]; const n = 2; const chunks = _.range(coll.length / n).map(i => coll.slice(i * n, (i + 1) * n)); console.log(chunks);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>
источник
Underscore изначально поддерживает _.chunk () начиная с версии 1.9.0.
const data = ["a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", "a11", "a12", "a13"]; const chunks = _.chunk(data, 4); console.log(chunks);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore.js"></script>
источник
попробуйте этот вариант, это гораздо практичнее (например, если вы хотите разделить массив на основе количества элементов, которые будут контейнером в каждом подмассиве):
function chunk(arr, start, amount){ var result = [], i, start = start || 0, amount = amount || 500, len = arr.length; do { //console.log('appending ', start, '-', start + amount, 'of ', len, '.'); result.push(arr.slice(start, start+amount)); start += amount; } while (start< len); return result; };
и использование в вашем случае:
var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17], chunked = chunk(arr, 0, Math.floor(arr.length/3)); //to get 4 nested arrays console.log(chunked);
и еще один случай:
var arr = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17], chunked = chunk(arr, 0, 3); // to get 6 nested arrays each containing maximum of 3 items console.log(chunked);
источник
start
параметр не очень практичен, imho. Обычно вы не хотите его проходить; но вам всегда нужно указывать размер блока. Лучше поменять местами эти два параметра.do while
петля? Никто не хочет получать пустые куски.