# 将数组拆分为大块

2020/09/24 13:01 · javascript ·  · 0评论

``["Element 1","Element 2","Element 3",...]; // with close to a hundred elements.``

array.slice方法可以从一开始，中间，或自己需要的任何目的数组的结束提取切片，在不改变原来的数组。

``````var i,j,temparray,chunk = 10;
for (i=0,j=array.length; i<j; i+=chunk) {
temparray = array.slice(i,i+chunk);
// do whatever
}``````

``````Object.defineProperty(Array.prototype, 'chunk_inefficient', {
value: function(chunkSize) {
var array = this;
return [].concat.apply([],
array.map(function(elem, i) {
return i % chunkSize ? [] : [array.slice(i, i + chunkSize)];
})
);
}
});

console.log(
[1, 2, 3, 4, 5, 6, 7].chunk_inefficient(3)
)
// [[1, 2, 3], [4, 5, 6], [7]]``````

``[[1,2,3]]~[]~[]~[] ~ [[4,5,6]]~[]~[]~[] ~ [[7]]``

``````// refresh page if experimenting and you already defined Array.prototype.chunk

Object.defineProperty(Array.prototype, 'chunk', {
value: function(chunkSize) {
var R = [];
for (var i = 0; i < this.length; i += chunkSize)
R.push(this.slice(i, i + chunkSize));
return R;
}
});

console.log(
[1, 2, 3, 4, 5, 6, 7].chunk(3)
)``````

``````Array.range = function(n) {
// Array.range(5) --> [0,1,2,3,4]
return Array.apply(null,Array(n)).map((x,i) => i)
};

Object.defineProperty(Array.prototype, 'chunk', {
value: function(n) {

// ACTUAL CODE FOR CHUNKING ARRAY:
return Array.range(Math.ceil(this.length/n)).map((x,i) => this.slice(i*n,i*n+n));

}
});``````

``````> JSON.stringify( Array.range(10).chunk(3) );
[[1,2,3],[4,5,6],[7,8,9],[10]]``````

``````var ceil = Math.ceil;

Object.defineProperty(Array.prototype, 'chunk', {value: function(n) {
return Array(ceil(this.length/n)).fill().map((_,i) => this.slice(i*n,i*n+n));
}});``````

``````Object.defineProperty(Array.prototype, 'chunk', {value: function(n) {
return Array.from(Array(ceil(this.length/n)), (_,i)=>this.slice(i*n,i*n+n));
}});``````

``````var perChunk = 2 // items per chunk

var inputArray = ['a','b','c','d','e']

var result = inputArray.reduce((resultArray, item, index) => {
const chunkIndex = Math.floor(index/perChunk)

if(!resultArray[chunkIndex]) {
resultArray[chunkIndex] = [] // start a new chunk
}

resultArray[chunkIndex].push(item)

return resultArray
}, [])

console.log(result); // result: [['a','b'], ['c','d'], ['e']]``````

``````inputArray.reduce((all,one,i) => {
const ch = Math.floor(i/perChunk);
all[ch] = [].concat((all[ch]||[]),one);
return all
}, [])``````

``````function chunk (arr, len) {

var chunks = [],
i = 0,
n = arr.length;

while (i < n) {
chunks.push(arr.slice(i, i += len));
}

return chunks;
}

// Optionally, you can do the following to avoid cluttering the global namespace:
Array.chunk = chunk;``````

``````function chunk(arr, chunkSize) {
var R = [];
for (var i=0,len=arr.length; i<len; i+=chunkSize)
R.push(arr.slice(i,i+chunkSize));
return R;
}``````

ECMA 6中的一线

``````const [list,chuckSize] = [[1,2,3,4,5,6,7,8,9,10,11,12,13,14,15], 6]

new Array(Math.ceil(list.length / chuckSize)).fill().map(_ => list.splice(0,chuckSize))``````

``````var chunks = function(array, size) {
var results = [];
while (array.length) {
results.push(array.splice(0, size));
}
return results;
};``````

``````Array.prototype.chunk = function ( n ) {
if ( !this.length ) {
return [];
}
return [ this.slice( 0, n ) ].concat( this.slice(n).chunk(n) );
};

[1,2,3,4,5,6,7,8,9,0].chunk(3);
> [[1,2,3],[4,5,6],[7,8,9],[0]]``````

``````const chunk = (arr, size) =>
arr
.reduce((acc, _, i) =>
(i % size)
? acc
: [...acc, arr.slice(i, i + size)]
, [])

// USAGE
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
chunk(numbers, 3)

// [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]``````

``````// 0: [[1, 2, 3]]
// 1: [[1, 2, 3]]
// 2: [[1, 2, 3]]
// 3: [[1, 2, 3], [4, 5, 6]]
// 4: [[1, 2, 3], [4, 5, 6]]
// 5: [[1, 2, 3], [4, 5, 6]]
// 6: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 7: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 8: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
// 9: [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]``````

# 使用发电机

``````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]]``````

``````const chunk = function(array, size) {
if (!array.length) {
return [];
}
const tail = array.slice(size);

};

console.log(chunk([1,2,3], 2));``````

``````function chunk(arr, n) {
return arr.slice(0,(arr.length+n-1)/n|0).
map(function(c,i) { return arr.slice(n*i,n*i+n); });
}``````

``chunk([1,2,3,4,5,6,7], 2);``

``````function chunker(p, c, i) {
(p[i/this|0] = p[i/this|0] || []).push(c);
return p;
}``````

``[1,2,3,4,5,6,7].reduce(chunker.bind(3),[]);``

``````// Fluent alternative API without prototype hacks.
function chunker(n) {
return function(p, c, i) {
(p[i/n|0] = p[i/n|0] || []).push(c);
return p;
};
}``````

``[1,2,3,4,5,6,7].reduce(chunker(3),[]);``

``````function chunk(arr, n) {
return arr.reduce(function(p, cur, i) {
(p[i/n|0] = p[i/n|0] || []).push(cur);
return p;
},[]);
}

chunk([1,2,3,4,5,6,7], 3);``````

``````function chunk(a, l) {
return new Array(Math.ceil(a.length / l)).fill(0)
.map((_, n) => a.slice(n*l, n*l + l));
}``````

``````function chunk(a, l) {
if (a.length == 0) return [];
else return [a.slice(0, l)].concat(chunk(a.slice(l), l));
}``````

ES6的可笑的弱数组功能令人困惑：-)

``````const chunk = (arr, size) => (
arr.reduce((acc, _, i) => {
if (i % size === 0) acc.push(arr.slice(i, i + size))
return acc
}, [])
)

// Usage:
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const chunked = chunk(numbers, 3)
console.log(chunked)``````

``````function chunk(arr, size) {
// This prevents infinite loops
if (size < 1) throw new Error('Size must be positive')

const result = []
for (let i = 0; i < arr.length; i += size) {
result.push(arr.slice(i, i + size))
}
return result
}``````

``````var result = [];

for (var i = 0; i < arr.length; i += size) {
result.push(arr.slice(i, size + i));
}
return result;``````
``````var result = [];

for (var i = 0; i < arr.length; i += size) {
result.push(arr.subarray(i, size + i));
}
return result;``````

``````function chunk(chunkSize, array) {
return array.reduce(function(previous, current) {
var chunk;
if (previous.length === 0 ||
previous[previous.length -1].length === chunkSize) {
chunk = [];   // 1
previous.push(chunk);   // 2
}
else {
chunk = previous[previous.length -1];   // 3
}
chunk.push(current);   // 4
return previous;   // 5
}, []);   // 6
}

console.log(chunk(2, ['a', 'b', 'c', 'd', 'e']));
// prints [ [ 'a', 'b' ], [ 'c', 'd' ], [ 'e' ] ]``````

`// nbr`以上各项的说明

1. 如果先前的值（即先前返回的块数组）为空，或者如果最后一个先前的块包含`chunkSize`，则创建一个新块
2. 将新块添加到现有块的数组中
3. 否则，当前块是块数组中的最后一个块
4. 将当前值添加到块中
5. 返回修改后的块数组
6. 通过传递一个空数组来初始化还原

``````var chunk3 = function(array) {
return chunk(3, array);
};

console.log(chunk3(['a', 'b', 'c', 'd', 'e']));
// prints [ [ 'a', 'b', 'c' ], [ 'd', 'e' ] ]``````

``````Object.defineProperty(Array.prototype, 'chunk', {
value: function(chunkSize) {
return this.reduce(function(previous, current) {
var chunk;
if (previous.length === 0 ||
previous[previous.length -1].length === chunkSize) {
chunk = [];
previous.push(chunk);
}
else {
chunk = previous[previous.length -1];
}
chunk.push(current);
return previous;
}, []);
}
});

console.log(['a', 'b', 'c', 'd', 'e'].chunk(4));
// prints [ [ 'a', 'b', 'c' 'd' ], [ 'e' ] ]``````
``````in coffeescript:

b = (a.splice(0, len) while a.length)

demo
a = [1, 2, 3, 4, 5, 6, 7]

b = (a.splice(0, 2) while a.length)
[ [ 1, 2 ],
[ 3, 4 ],
[ 5, 6 ],
[ 7 ] ]``````
``````results = []
chunk_size = 10
while(array.length > 0){
results.push(array.splice(0, chunk_size))
}``````

``[11,22,33,44,55].map((_, i, all) => all.slice(2*i, 2*i+2)).filter(x=>x.length)``

``````const array_chunks = (array, chunk_size) => array
.map((_, i, all) => all.slice(i*chunk_size, (i+1)*chunk_size))
.filter(x => x.length)``````

``````var segment = (arr, n) => arr.reduce((r,e,i) => i%n ? (r[r.length-1].push(e), r)
: (r.push([e]), r), []),
arr = Array.from({length: 31}).map((_,i) => i+1);
res = segment(arr,7);
console.log(JSON.stringify(res));``````

``````function chunk(arr,n){
var r = Array(Math.ceil(arr.length/n)).fill();
return r.map((e,i) => arr.slice(i*n, i*n+n));
}

arr = Array.from({length: 31},(_,i) => i+1);
res = chunk(arr,7);
console.log(JSON.stringify(res));``````

``````lodash.chunk(arr,<size>).forEach(chunk=>{
console.log(chunk);
})``````

``````Array.prototype.chunk = function(size) {
let result = [];

while(this.length) {
result.push(this.splice(0, size));
}

return result;
}

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log(arr.chunk(2));``````

### 更新资料

`Array.prototype.splice()`填充原始数组，执行`chunk()`完原始数组（`arr`）后变为`[]`

``````Array.prototype.chunk = function(size) {
let data = [...this];
let result = [];

while(data.length) {
result.push(data.splice(0, size));
}

return result;
}

const arr = [1, 2, 3, 4, 5, 6, 7, 8, 9];
console.log('chunked:', arr.chunk(2));
console.log('original', arr);``````

PS：感谢@ mts-knn提到此事。

``````    const array = [86,133,87,133,88,133,89,133,90,133];
const new_array = [];

const chunksize = 2;
while (array.length) {
const chunk = array.splice(0,chunksize);
new_array.push(chunk);
}

console.log(new_array)``````

`popularProducts`输入数组在哪里`5`块大小在哪里

``````import splitEvery from 'ramda/src/splitEvery'

splitEvery(5, popularProducts).map((chunk, i) => {
// do something with chunk

})``````

ES6单线方法基于`Array.prototype` `reduce``push`方法：

``````const doChunk = (list, size) => list.reduce((r, v) =>
(!r.length || r[r.length - 1].length === size ?
r.push([v]) : r[r.length - 1].push(v)) && r
, []);

console.log(doChunk([0,1,2,3,4,5,6,7,8,9,10,11,12], 5));
// [[0, 1, 2, 3, 4], [5, 6, 7, 8, 9], [10, 11, 12]]``````

ES6 Generator版本

``````function* chunkArray(array,size=1){
var clone = array.slice(0);
while (clone.length>0)
yield clone.splice(0,size);
};
var a = new Array(100).fill().map((x,index)=>index);
for(const c of chunkArray(a,10))
console.log(c);``````

``````function chunk(array, chunkSize) {
let chunkCount = Math.ceil(array.length / chunkSize);
let chunks = new Array(chunkCount);
for(let i = 0, j = 0, k = chunkSize; i < chunkCount; ++i) {
chunks[i] = array.slice(j, k);
j = k;
k += chunkSize;
}
return chunks;
}``````

ES6传播功能性#ohmy #ftw

``````const chunk =
(size, xs) =>
xs.reduce(
(segments, _, index) =>
index % size === 0
? [...segments, xs.slice(index, index + size)]
: segments,
[]
);

console.log( chunk(3, [1, 2, 3, 4, 5, 6, 7, 8]) );``````

# 这是一个尾部调用优化的递归解决方案。

``````const splitEvery = (n, xs, y=[]) =>
xs.length===0 ? y : splitEvery(n, xs.slice(n), y.concat([xs.slice(0, n)]))

console.log(splitEvery(2, [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]))``````