将一个JS数组分割成N个数组

想象一下,我有这样一个JS数组:

var a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]; 

我想要的是将该数组分割成N个较小的数组。 例如:

 split_list_in_n(a, 2) [[1, 2, 3, 4, 5, 6], [7, 8, 9, 10, 11]] For N = 3: [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11]] For N = 4: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11]] For N = 5: [[1, 2, 3], [4, 5], [6, 7], [8, 9], [10, 11]] 

对于Python,我有这样的:

 def split_list_in_n(l, cols): """ Split up a list in n lists evenly size chuncks """ start = 0 for i in xrange(cols): stop = start + len(l[i::cols]) yield l[start:stop] start = stop 

对于JS来说,我能想出的最好的解决scheme是recursion函数,但是我不喜欢它,因为它很复杂和难看。 这个内部函数返回一个像这样的数组[1,2,3,null,4,5,6,null,7,8],然后我必须再次循环并手动分割它。 (我的第一个尝试是返回这个:[1,2,3,[4,5,6,[7,8,9]],我决定用空分隔符来做)。

 function split(array, cols) { if (cols==1) return array; var size = Math.ceil(array.length / cols); return array.slice(0, size).concat([null]).concat(split(array.slice(size), cols-1)); } 

这是一个jsfiddle的: http : //jsfiddle.net/uduhH/

你会怎么做? 谢谢!

您可以使切片“平衡”(子arrays的长度差异尽可能小)或“偶数”(所有子arrays,但最后一个长度相同):

 function chunkify(a, n, balanced) { if (n < 2) return [a]; var len = a.length, out = [], i = 0, size; if (len % n === 0) { size = Math.floor(len / n); while (i < len) { out.push(a.slice(i, i += size)); } } else if (balanced) { while (i < len) { size = Math.ceil((len - i) / n--); out.push(a.slice(i, i += size)); } } else { n--; size = Math.floor(len / n); if (len % size === 0) size--; while (i < size * n) { out.push(a.slice(i, i += size)); } out.push(a.slice(size * n)); } return out; } /////////////////////// onload = function () { function $(x) { return document.getElementById(x); } function calc() { var s = +$('s').value, a = []; while (s--) a.unshift(s); var n = +$('n').value; $('b').textContent = JSON.stringify(chunkify(a, n, true)) $('e').textContent = JSON.stringify(chunkify(a, n, false)) } $('s').addEventListener('input', calc); $('n').addEventListener('input', calc); calc(); } 
 <p>slice <input type="number" value="20" id="s"> items into <input type="number" value="6" id="n"> chunks:</p> <pre id="b"></pre> <pre id="e"></pre> 

我只是做了一个迭代实现的algorithm: http : //jsfiddle.net/ht22q/ 。 它通过你的testing用例。

 function splitUp(arr, n) { var rest = arr.length % n, // how much to divide restUsed = rest, // to keep track of the division over the elements partLength = Math.floor(arr.length / n), result = []; for(var i = 0; i < arr.length; i += partLength) { var end = partLength + i, add = false; if(rest !== 0 && restUsed) { // should add one element for the division end++; restUsed--; // we've used one division element now add = true; } result.push(arr.slice(i, end)); // part of the array if(add) { i++; // also increment i in the case we added an extra element for division } } return result; } 
 function split(arr, n) { var res = []; while (arr.length) { res.push(arr.splice(0, n)); } return res; } 

你可以把它缩减成一个matrix。 下面的例子将数组( arr )分割成两个位置数组的matrix。 如果你想要其他尺寸,只需更改第二行的2值:

 target.reduce((memo, value, index) => { if (index % 2 == 0 && index !== 0) memo.push([]) memo[memo.length - 1].push(value) return memo }, [[]]) 

希望它有帮助!

编辑:因为有些人仍然评论这不会回答这个问题,因为我正在修复每个块大小,而不是我想要的块数 。 这里是解释我想在解释部分解释的代码:使用target.length

 // Chunk function const chunk = (target, size) => { return target.reduce((memo, value, index) => { // Here it comes the only difference if (index % (target.length / size) == 0 && index !== 0) memo.push([]) memo[memo.length - 1].push(value) return memo }, [[]]) } // Usage write(chunk([1, 2, 3, 4], 2)) write(chunk([1, 2, 3, 4], 4)) // For rendering pruposes. Ignore function write (content) { document.write(JSON.stringify(content), '</br>') } 

老问题,但由于vanillaJS不是一个必要条件,所以很多人都试图用lodash / chunk来解决这个问题,而且不会误认为_.chunk实际上做了什么, _.chunk是一个使用lodash的简洁+准确的解决scheme:

(与接受的答案不同,即使originalArray.length < numCols )也保证n列)

 import _chunk from 'lodash/chunk' /** * Split an array into n subarrays (or columns) * @param {Array} flatArray Doesn't necessarily have to be flat, but this func only works 1 level deep * @param {Number} numCols The desired number of columns * @return {Array} */ export function splitArray(flatArray, numCols){ const maxColLength = Math.ceil(flatArray.length/numCols) const nestedArray = _chunk(flatArray, maxColLength) let newArray = [] for (var i = 0; i < numCols; i++) { newArray[i] = nestedArray[i] || [] } return newArray } 

在最后的for循环是保证所需数量的“列”。

recursion方法,未经testing。

 function splitArray(array, parts, out) { var len = array.length , partLen if (parts < len) { partLen = Math.ceil(len / parts); out.push(array.slice(0, partLen)); if (parts > 1) { splitArray(array.slice(partLen), parts - 1, out); } } else { out.push(array); } } 

另一个recursion工作得很好,这是不那么难看

 function nSmaller(num, arr, sliced) { var mySliced = sliced || []; if(num === 0) { return sliced; } var len = arr.length, point = Math.ceil(len/num), nextArr = arr.slice(point); mySliced.push(arr.slice(0, point)); nSmaller(num-1, nextArr, mySliced); return(mySliced); } 

只需使用lodash的chunk函数将数组分割成更小的数组https://lodash.com/docs#chunk不需要摆弄循环了!;

可能更干净的方法将是以下(不使用任何其他库):

 var myArray = []; for(var i=0; i<100; i++){ myArray.push(i+1); } console.log(myArray); function chunk(arr, size){ var chunkedArr = []; var noOfChunks = Math.ceil(arr.length/size); console.log(noOfChunks); for(var i=0; i<noOfChunks; i++){ chunkedArr.push(arr.slice(i*size, (i+1)*size)); } return chunkedArr; } var chunkedArr = chunk(myArray, 3); console.log(chunkedArr); 

我已经创build了自己的数组,将被分块。 你可以在这里find代码

另外我们在lodash库里有一个很好用的方法“chunk”。 希望有所帮助

我这样做,它的工作…

 function splitArray(array, parts) { if (parts< array.length && array.length > 1 && array != null) { var newArray = []; var counter1 = 0; var counter2 = 0; while (counter1 < parts) { newArray.push([]); counter1 += 1; } for (var i = 0; i < array.length; i++) { newArray[counter2++].push(array[i]); if (counter2 > parts - 1) counter2 = 0; } return newArray; } else return array; } 

检查我的版本这个数组拆分

 // divide array Array.prototype.divideIt = function(d){ if(this.length <= d) return this; var arr = this, hold = [], ref = -1; for(var i = 0; i < arr.length; i++){ if(i % d === 0){ ref++; } if(typeof hold[ref] === 'undefined'){ hold[ref] = []; } hold[ref].push(arr[i]); } return hold; }; 

如果你知道想设置child_arrays.length那么我认为这个解决scheme最好的:

 function sp(size, arr){ //size - child_array.length var out = [],i = 0, n= Math.ceil((arr.length)/size); while(i < n) { out.push(arr.splice(0, (i==n-1) && size < arr.length ? arr.length: size)); i++;} return out; } 

调用fn:sp(2,[1,2,3,4,5,6,7,8,9,10,11])// 2 – child_arrat.length

答案:[1,2],[3,4],[5,6],[7,8],[9,10],[11]

如果你使用lodash,你可以像下面这样简单地实现它:

 import {chunk} from 'lodash'; // divides the array into 2 sections chunk([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11], 2); // => [[1,2,3,4,5,6], [7,8,9,10,11]]