다음과 같은 Javascript 배열이 있다고 가정 해 봅시다.
["Element 1","Element 2","Element 3",...]; // with close to a hundred elements.
예를 들어 최대 10 개의 요소를 사용하여 배열을 여러 개의 작은 배열로 청크 (분할)하는 데 어떤 접근법이 적합합니까?
답변
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
}
답변
dbaseman의 답변에서 수정되었습니다 : https://stackoverflow.com/a/10456344/711085
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]]
작은 부록 :
위의 내용은 사용하기에 우아하지 않은 (내 마음에) 해결 방법이라는 것을 지적해야합니다 Array.map
. 기본적으로 다음을 수행합니다. 여기서 ~는 연결입니다.
[[1,2,3]]~[]~[]~[] ~ [[4,5,6]]~[]~[]~[] ~ [[7]]
아래 방법과 동일한 점근 적 실행 시간을 갖지만 빈 목록을 작성하기 때문에 더 나쁜 상수 요인 일 수 있습니다. 이것을 다음과 같이 다시 작성할 수 있습니다 (대부분 Blazemonger의 방법과 동일하므로 원래이 답변을 제출하지 않은 이유입니다).
보다 효율적인 방법 :
// 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]]
또는 Array.range 함수를 원하지 않으면 실제로는 하나의 라이너 (플러 프 제외)입니다.
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));
}});
답변
다음은 reduce를 사용하는 ES6 버전입니다.
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']]
그리고 추가 맵 / 축소 변환을 연결할 준비가되었습니다. 입력 배열이 그대로 남아 있습니다
더 짧지 만 읽기 어려운 버전을 선호하는 경우 concat
동일한 최종 결과를 위해 일부 를 믹스에 뿌릴 수 있습니다.
inputArray.reduce((all,one,i) => {
const ch = Math.floor(i/perChunk);
all[ch] = [].concat((all[ch]||[]),one);
return all
}, [])
답변
누가 코드를 사용할지 모르는 경우 (타사, 동료, 나중에 자신 등) Array.prototype을 포함한 기본 프로토 타입을 사용하지 않도록하십시오.
프로토 타입을 안전하게 확장 할 수있는 방법이 있지만 (모든 브라우저가 아님) 확장 된 프로토 타입에서 생성 된 객체를 안전하게 소비 할 수있는 방법이 있지만 가장 좋은 방법 은 최소한의 놀람 원칙 을 따르고 이러한 방법을 모두 피하는 것입니다.
시간이 있다면 Andrew Dupont의 JSConf 2011 강연에서 “모든 것이 허용됨 : 내장 기능 확장”을 보고이 주제에 대한 좋은 토론을하십시오.
그러나 질문으로 돌아 가면 위의 솔루션은 작동하지만 지나치게 복잡하고 불필요한 계산 오버 헤드가 필요합니다. 내 해결책은 다음과 같습니다.
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;
답변
jsperf.com에 대한 다른 답변을 테스트했습니다. 결과는 https://web.archive.org/web/20150909134228/https://jsperf.com/chunk-mtds에서 확인할 수 있습니다.
그리고 가장 빠른 기능은 IE8에서 작동합니다.
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;
}
답변
스플 라이스 방법 을 사용하고 싶습니다 .
var chunks = function(array, size) {
var results = [];
while (array.length) {
results.push(array.splice(0, size));
}
return results;
};
답변
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))