배열을 청크로 나누기


516

다음과 같은 Javascript 배열이 있다고 가정 해 봅시다.

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

예를 들어 최대 10 개의 요소를 사용하여 배열을 여러 개의 작은 배열로 청크 (분할)하는 데 어떤 접근법이 적합합니까?




24
들어 lodash 사용자, 당신이 찾고있는 _.chunk .
Ulysse BN

2
방금 const chunk = (arr, n) => arr.length ? [arr.slice(0, n), ...chunk(arr.slice(n), n)] : []멋지고 짧은 시도했지만 1,000 요소에 대한 @AymKdn의 대답만큼 256x, 10,000 요소에 대해 1,058x만큼 걸리는 것 같습니다!
Toph

당신은 또한 마지막 청크의 최소 크기를 필요로하는 경우, 여기에 옵션은 다음과 같습니다 stackoverflow.com/questions/57908133/...
아멧 세틴

답변:


640

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
}

19
이것이 chunk존재하지 않도록 하는 util 함수인지 기억하십시오 0. (무한한 루프)
Steven Lu

19
아니, 마지막 덩어리는 다른 덩어리보다 작아야합니다.
Blazemonger

7
@Blazemonger, 정말로! 다음에는 결론에 도달하기 전에 실제로 직접 시도해 보겠습니다. 나는 배열의 범위를 초과하는 array.slice에 입력을 전달하는 것이 문제가 될 것이라고 가정했지만 (정확하지는 않습니다) 완벽하게 작동합니다!
rysqui

55
원 라이너 (체인 애호가) : const array_chunks = (array, chunk_size) => Array(Math.ceil(array.length / chunk_size)).fill().map((_, index) => index * chunk_size).map(begin => array.slice(begin, begin + chunk_size));.
Константин Ван

8
왜 J가 필요합니까? 먼저 최적화라고 생각했지만 실제로는 for (i = 0; i <array.length; i ++) {}보다 느리다
Alex

149

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));
}});

41
Eh, chunk배열 에서 함수 를 호출하여 얻는 시원함이 실제로 추가하는 추가 복잡성과 내장 프로토 타입을 어지럽히는 미묘한 버그를 능가하지 않기 때문에 프로토 타입을 어지럽히 지 않습니다.
Gordon Gustafson

12
그는 그것들을 어지럽히 지 않고 배열을 위해 확장하고 있습니다. Object.prototype을 만지지 마십시오. 모든 객체 (모든 것)에 버블 링되기 때문에이 배열 특정 기능에 대해서는 아무런 문제가 없습니다.
rlemon

확신 그것은해야 array.map(function(i)하지 array.map(function(elem,i)생각
나이젤 천사

3
mozilla dev 사이트의 호환성 차트 (IE9 + 용 Array.map)를 기반으로합니다. 조심해.
Maikel D

예측할 수없는 덩어리로 리드 - 7.5 숫자의 유형 - 부동 전달하는주의
갈 Bracha의

103

다음은 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
}, [])

이것은 가장 응축 된 솔루션처럼 보입니다. chunkIndex = Math.floor (index / perChunk)는 무엇입니까? 평균입니까?
me-me

5/2 = 2.5Math.floor(2.5) = 2인덱스 5 항목은 버킷 2에 배치 할 수 있도록
안드레이 R

감사합니다 Andrei R. Ah 0-2까지 단계별로 진행됩니다. 수학 용어로 불리는 것은 무엇입니까? 내 요점은 각 슬라이스의 인덱스를 얻기 위해 index / 2를 모든 인덱스로 나눈다 고 생각하지 않았을 것입니다. 그래서 나는 그것을 정말로 좋아하지만 수학 용어로 완전히 이해하지 못하기 때문에 머리를 감싸려고합니다. 나는 보통 총 수의 평균을 얻기 위해 이것을하지만, 이것은 다르게 보입니다.
me-me

이 솔루션은 모든 요소를 ​​반복해야하기 때문에 다른 솔루션과 비교할 때 비효율적입니다.
JP de la Torre

당신은 맞습니다 @JPdelaTorre, 아마도 배열을 슬라이스하는 솔루션만큼 효율적이지 않지만 여기서 머리카락을 나눕니다. 나열된 대부분의 답변은 해당 정의에 따라 비효율적입니다.
Andrei R

102

누가 코드를 사용할지 모르는 경우 (타사, 동료, 나중에 자신 등) 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;

25
"원시 프로토 타입으로 뭉개지 말 것"새로운 js 개발자는이 문구의 문신을 영구적이지는 않지만 일시적으로 얻어야합니다.
Jacob Dalton

2
나는 몇 년 동안 자바 스크립트를 사용해 왔으며 가장 많은 호출 함수에서 프로토 타입을 귀찮게하지 않고 다른 사람들이 보는 것처럼 수정하지 마십시오.
1984 년

2
내 눈에 가장 좋은 제안, 이해하고 구현하는 가장 간단한 제안, 대단히 감사합니다!
Olga Farber

1
@JacobDalton 모든 대학의 잘못이라고 생각합니다. 사람들은 어디에서나 OOP를 사용해야한다고 생각합니다. 그래서 그들은 "단지 함수를 만드는 것"이 ​​두렵습니다. 그들은 그것을 무언가 안에 넣기를 원합니다. 전혀 적절하지 않더라도. 점 표기법이 없으면 "아키텍처"가 없습니다.
Gherman

51

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;
}

1
이 벤치마킹을 해주신 @AymKdn에게 감사드립니다 : 정말 도움이되었습니다! 스플 라이스 방식 을 사용 중이며 884432의 청크 크기로 Chrome v70 브라우저가 다운되었습니다. 제안 된 "슬라이스"방식을 사용하면 코드가 더 이상 브라우저의 "렌더링"프로세스와 충돌하지 않습니다. :)
Benny Neugebauer

34

스플 라이스 방법 을 사용하고 싶습니다 .

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

16
이 스플 라이스 솔루션은 원래 배열을 수정하므로주의해서 사용해야하므로 부작용을 명확하게 문서화해야합니다.
bdrx

3
그런 다음 대신 slice를 사용하십시오
mplungjan

@mplungjan slice를 사용할 때 결과는 계속 같은 배열이됩니다. 따라서 더 이상 수정하지 않고 대체품이 아닙니다.
nietonfir

이 답변에 추가 할 유일한 것은 원래 배열 의 복제본 입니다. ES6의 스프레드 연산자로 그렇게 할 것입니다. var clone = [...array]그런 다음 복제 된 어레이를 통해 길이를 확인하고 접합합니다.
MauricioLeal

1
또는 ES6 기능을 사용할 수없는 경우 단순 array = array.slice()사본을 작성하기 만하면 됩니다.
3limin4t0r

34

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))

9
원래 list배열을 수정합니다
Jacka

6
.slice ()를 사용한 손쉬운 수정 .. .map((_,i) => list.slice(i*chuckSize,i*chuckSize+chuckSize))
James Robey

2
JSPerf에서 이것은 다른 많은 답변보다 훨씬 성능이 뛰어납니다.
Micah Henning

30

오래된 질문 : 새로운 답변! 나는 실제로이 질문에 대한 답변으로 일하고 있었고 친구가 그것을 개선하도록했습니다! 그래서 여기 있습니다 :

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

14
참고로,이 방법의 성능은 O (N ^ 2)이므로 성능에 중요한 코드 섹션이나 긴 배열 (특히 배열 .length이 청크 크기보다 훨씬 큰 경우)에는 사용해서는 안됩니다 n. 이것이 자바 스크립트와 달리 게으른 언어라면,이 알고리즘은 O (N ^ 2) 시간을 겪지 않을 것입니다. 즉, 재귀 구현은 우아합니다. 당신은 아마 처음 도우미 함수를 정의하여 성능을 개선하기 위해 수정할 수 재귀에 array,position다음 파견 : Array.prototype.chunk리턴 [당신의 도우미 함수 (...)
ninjagecko

덕분에 내가 chanelled해야합니다 당신의 정신을 오늘 밤에 저를 축복 센
물린

1
또는 ...var chunk = (arr, n) => { if ( !arr.length ) return []; return [ arr.slice( 0, n ) ].concat( chunk(arr.slice(n), n) ) }
Ed Williams

28

요즘 lodash의 청크 함수를 사용하여 배열을 더 작은 배열로 나눌 수 있습니다 https://lodash.com/docs#chunk 더 이상 루프를 피할 필요가 없습니다!


3
나는 자바 스크립트 질문에 대한 면책 ​​조항이 있어야한다고 생각합니다. 노드 또는 브라우저에 가장 먼저 포함시키는 것은.
Jacob Dalton

20

많은 답변이 있었지만 이것이 내가 사용하는 것입니다.

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

먼저 인덱스를 청크 크기로 나눌 때 나머지를 확인하십시오.

나머지가있는 경우 누산기 배열을 반환하십시오.

나머지가 없으면 인덱스를 청크 크기로 나눌 수 있으므로 원래 배열에서 슬라이스를 가져 와서 (현재 인덱스에서 시작하여) 어큐뮬레이터 배열에 추가하십시오.

따라서 reduce의 각 반복에 대해 반환 된 누산기 배열은 다음과 같습니다.

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

반복의 멋진 솔루션과 멋진 시각적 표현. 나는 대답으로 게시 한 매우 유사한 솔루션으로 끝났습니다 : stackoverflow.com/a/60779547
mts knn

15

발전기 사용

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


3
나는 발전기를 거의 사용하거나 더 복잡한 방식으로 사용하는이 질문에 대한 모든 대답에 놀랐습니다. 이 솔루션의 간결함과 성능.
Keith

14

좋아, 아주 단단한 것으로 시작합시다.

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),[]);

새끼 고양이가 this숫자에 묶이면 죽기 때문에 대신 다음과 같이 수동 카레를 할 수 있습니다.

// 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);

iE8에서 작동하지 않습니다.
Nadeemmnn Mohd 2016 년

4
하아! 나는 새끼 고양이의 의견을 좋아한다. 추가적인 건설적인 입력이 없어서 죄송합니다 :)
29er

내가 할 (p[i/n|0] || (p[i/n|0] = []))것이므로, 필요하지 않으면 값을 할당하지 않습니다.
yckart

12

순수한 ES6에서 간단한 비 돌연변이 솔루션을 만드는 것을 목표로했습니다. 자바 스크립트의 특성으로 인해 매핑하기 전에 빈 배열을 채워야합니다.

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의 엄청나게 약한 배열 기능은 좋은 퍼즐을 만듭니다 :-)


1
나도 이런 식으로 내 글을 썼습니다. 0에서 를 제거하면 여전히 작동 fill하여 fill모양을 좀 더 합리적으로 보이게 만듭니다 .
Coert Grobbelaar

12

나는 이것이 ES6 구문을 가진 훌륭한 재귀 솔루션이라고 생각합니다.

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

  return [head, ...chunk(tail, size)];
};

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


9

https://www.npmjs.com/package/array.chunk에 대한 npm 패키지를 만들었습니다.

var result = [];

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

TypedArray를 사용하는 경우

var result = [];

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

@ A1rPun 내 나쁜, 나는 거기에 의견을 추가하지 않았습니다. 하지만, 대신 사용할 수있는 slice방법 이 없습니다. 대신 developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…를TypedArray 사용할 수 있습니다.subarray
zhiyelee

8

EcmaScript 버전> = 5.1을 사용하는 경우 O (N) 복잡도를 가진 array.reduce ()chunk() 사용 의 기능 버전을 구현할 수 있습니다 .

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. 빈 배열을 전달하여 축소를 초기화하십시오.

다음을 기반으로 한 카레 chunkSize:

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

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

chunk()전역 Array객체에 함수를 추가 할 수 있습니다 .

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


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

a.splice (0, 2)는 a에서 a [0..1]의 하위 배열을 제거하고 하위 배열 a [0..1]을 반환합니다. 나는 그 모든 배열의 배열을 만들고 있습니다
Arpit Jain

2
splice () 대신 비파괴 슬라이스 () 메서드를 사용하는 것이 좋습니다.
Ash Blue

7
results = []
chunk_size = 10
while(array.length > 0){
   results.push(array.splice(0, chunk_size))
}

1
왜 이것이 다운 투표되었는지 확실하지 않지만 코드는 약간의 설명을 사용할 수 있습니다.
jpaugh

2
스플 라이스는 원래 배열을 파괴하기 때문입니다.
metalim

7

다음 ES2015 접근 방식은 함수를 정의하지 않고 익명 배열에 직접 (청크 크기 2의 예) 작동합니다.

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

이를 위해 함수를 정의하려는 경우 다음과 같이 수행 할 수 있습니다 ( Blazemonger의 답변 에 대한 K._의 설명 개선 ).

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

6

그리고 이것이이 주제에 대한 나의 기여가 될 것입니다. .reduce()가장 좋은 방법 이라고 생각 합니다.

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));

그러나 .reduce()모든 arr기능을 통해 실행 되므로 위의 구현은 그리 효율적이지 않습니다 . 보다 빠른 접근 방식 (가장 빠른 명령에 가장 근접한)은 축소 된 (청크 될) 배열을 반복하여 크기를 미리 계산할 수 있기 때문 Math.ceil(arr/n);입니다. Array(Math.ceil(arr.length/n)).fill();나머지 결과처럼 빈 결과 배열이 있으면 배열 조각을 arr배열로 매핑하는 것입니다.

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));



4

기능적 솔루션의 경우 Ramda를 사용하십시오 .

popularProducts입력 배열은 어디에 있습니까 5, 청크 크기는

import splitEvery from 'ramda/src/splitEvery'

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

})


4

ES6 단선 접근 방식 Array.prototype reducepush방법 :

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

4

ES6 생성기 버전

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);

const대신 사용하십시오 .
Константин Ван

4

이것은 내가 생각할 수있는 가장 효율적이고 간단한 솔루션입니다.

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;
}

4

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]) );


4

다음은 테일 콜 최적화 인 재귀 솔루션입니다.

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


4

다음을 사용하는 하나 이상의 솔루션 arr.reduce():

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)

이 솔루션은 Steve Holgado솔루션 과 매우 유사합니다 . 그러나이 솔루션은 배열 확산을 사용하지 않고 감속기 함수에서 새 배열을 만들지 않기 때문에 다른 솔루션보다 빠르며 ( jsPerf 테스트 참조 ) 더 읽기 쉽고 (더 간단한 구문) 것입니다.

각에서 제 n (여기서 반복 N = size상기 제 1 반복에서 시작), 어큐뮬레이터 어레이 ( acc) 배열 (덩어리로 부가된다 arr.slice(i, i + size)), 그리고 복귀. 다른 반복에서는 누산기 배열이 그대로 반환됩니다.

경우 size제로, 메소드는 하늘의 배열을 돌려줍니다. 경우 size음수, 메소드가 리턴 결과를 깨진. 따라서 귀하의 경우에 필요한 경우 음수 또는 양수가 아닌 것에 대해 무언가를 원할 수 있습니다 size.


귀하의 경우 속도가 중요한 경우 간단한 for루프가 사용하는 것보다 빠르며 arr.reduce()( jsPerf 테스트 참조 ) 일부는이 스타일을 더 읽기 쉽습니다 .

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
}

2

편집 : @ mblase75는 내 글을 쓰는 동안 이전 답변에 더 간결한 코드를 추가 했으므로 그의 해결책을 따르는 것이 좋습니다.

다음과 같은 코드를 사용할 수 있습니다.

var longArray = ["Element 1","Element 2","Element 3", /*...*/];
var smallerArrays = []; // will contain the sub-arrays of 10 elements each
var arraySize = 10;
for (var i=0;i<Math.ceil(longArray.length/arraySize);i++) {
    smallerArrays.push(longArray.slice(i*arraySize,i*arraySize+arraySize));
}

arraySize더 작은 배열의 최대 길이를 변경하려면 값 을 변경하십시오.


2

다음은 재귀와 slice () 만 사용하는 비 변동 솔루션입니다.

const splitToChunks = (arr, chunkSize, acc = []) => (
    arr.length > chunkSize ?
        splitToChunks(
            arr.slice(chunkSize),
            chunkSize,
            [...acc, arr.slice(0, chunkSize)]
        ) :
        [...acc, arr]
);

그리고 단순히 좋아 사용 splitToChunks([1, 2, 3, 4, 5], 3)얻을 [[1, 2, 3], [4, 5]].

시도해 볼만한 바이올린은 다음과 같습니다. https://jsfiddle.net/6wtrbx6k/2/

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.