配列をチャンクに分割


516

次のようなJavascript配列があるとします。

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

配列を多数の小さな配列に分割(分割)するには、たとえば最大で10要素とするとどのようなアプローチが適切でしょうか。




24
lodashユーザー、あなたが探している_.chunk
Ulysse BN 2017

2
私は試してみましconst chunk = (arr, n) => arr.length ? [arr.slice(0, n), ...chunk(arr.slice(n), n)] : []たが、どれが素晴らしくて短いのでしょうか?@AymKdnの回答が1,000要素の場合は約256倍、10,000要素の場合は1,058倍の時間がかかるようです。
Toph

あなたはまた、最後のチャンクの最小サイズが必要な場合は、ここでのオプションは次のとおりです。stackoverflow.com/questions/57908133/...
アフメットCetin

回答:


641

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
これはに対してアサートするutilの機能である場合に注意してくださいchunkという0。(無限ループ)
Steven Lu

19
いいえ、最後のチャンクは他のチャンクよりも小さくなければなりません。
Blazemonger 14

7
@Blazemonger、確かに!次回は、結論にジャンプする前に実際に試してみることにします。配列の境界を超える入力をarray.sliceに渡すことは問題になると(誤って)想定していましたが、完全に機能します!
rysqui 14

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関数が必要ない場合は、実際には1行(綿毛を除く)です。

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
ええと、chunk配列の関数を呼び出すことで得られるクールさの感覚は、追加する複雑さと、組み込みのプロトタイプをいじくる微妙なバグを上回らないため、プロトタイプをいじることは避けます。
Gordon Gustafson、2012

12
彼は配列を拡張するためにそれらをいじっていません。Object.prototypeには触れないでください。これはすべてのオブジェクト(すべて)にバブルするためですが、この配列固有の関数では問題は発生しません。
rlemon 2012

かなり確信する必要があることarray.map(function(i)ではないarray.map(function(elem,i)けれども
ナイジェル・エンジェル

3
Mozilla開発サイトの互換性チャートに基づく、IE9 +用のArray.map。注意してください。
マイケルD 2013

浮動小数点を渡すように注意してください
-7.5

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.5そしてMath.floor(2.5) = 2、インデックス5を有する項目には、バケット2に配置されます
アンドレイR

Andrei R. Ahに感謝します。0から2に進みます。数学用語でこれを何と呼びますか?私のポイントは、各スライスのインデックスを取得するために、インデックス/ 2のすべてのインデックスを分割することを考えたことはなかったと思います。私は本当に好きだから数学の言葉で完全に理解していないので、私はそれに頭を抱えようとしています。私は通常、総数の平均を取得するためにこれを行いますが、これは異なって見えます。
me-me

すべての要素を反復処理する必要があるため、他のソリューションと比較すると、このソリューションは非効率的です。
JP de la Torre

あなたは正しい@JPdelaTorre、それはおそらく配列をスライスするソリューションほど効率的ではありませんが、ここでヘアを分割しています。リストされているほとんどの回答は、その定義では非効率的です。
Andrei R

102

誰がコードを消費するのかわからない場合(サードパーティ、同僚、後日自分自身など)、Array.prototypeなどのネイティブプロトタイプをいじらないようにしてください。

プロトタイプを安全に拡張する方法があります(すべてのブラウザーではありません)。拡張プロトタイプから作成されたオブジェクトを安全に使用する方法がありますが、より良い経験則は、 、最小サプライズ原則これらのプラクティスを完全に回避することです。

時間があれば、Andrew DupontのJSConf 2011の講演をご覧ください。 「Everything is Permitted:Extending Built-ins」でこのトピックについての良い議論を。

しかし、質問に戻ると、上記のソリューションは機能しますが、非常に複雑であり、不必要な計算オーバーヘッドが必要です。これが私の解決策です:

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開発者は、このフレーズの一時的ではなくても一時的な入れ墨を取得する必要があります。
ジェイコブダルトン

2
私は何年もJavaScriptを使用しており、ほとんどの呼び出し関数でプロトタイプに悩まされることはほとんどありません。
1984年

2
私の目に最高の提案、理解するのが最も簡単で、実装において、ありがとうございました!
Olga Farber、

1
@JacobDalton大学のせいだと思います。OOPはどこでも使用する必要があると人々は考えています。したがって、彼らは「関数を作成するだけ」を恐れています。彼らはそれを何かの中に確実に入れたいのです。それがまったく適切でなくても。ドット表記がない場合、「アーキテクチャ」はありません。
ガーマン

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に感謝:これはとても役に立ちました!私はスプライスアプローチを使用していて、Chrome v70ブラウザーをチャンクサイズ884432でクラッシュさせました。提案された「スライス」アプローチを使用すると、コードはブラウザーの「レンダリング」プロセスをクラッシュさせません。:)
ベニー

34

私はスプライス方法を使用したいと思います:

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

16
このスプライスソリューションは元の配列を変更するため、注意が必要です。副作用を明確に文書化してください。
bdrx

3
次に、代わりにスライスを使用します
mplungjan 2015

@mplungjanスライスを使用すると、結果は何度も同じ配列になります。したがって、これは実際には、いくつかの追加の変更なしのドロップイン置換ではありません。
nietonfir 2016年

この回答に追加する唯一のものは、元のアレイへのクローンです。ES6のスプレッドオペレーターでそれを行います。var clone = [...array]次に、そのクローンされたアレイに対して、長さのチェックとスプライシングを行います。
MauricioLeal 2017年

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 '18 / 07/18

6
.slice()。を使用した簡単な修正 .map((_,i) => list.slice(i*chuckSize,i*chuckSize+chuckSize))
James Robey

2
JSPerfでは、これは他の多くの回答よりも大幅にパフォーマンスが優れています。
ミカヘニング

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
fyi、このメソッドのパフォーマンスはO(N ^ 2)であるため、コードのパフォーマンスが重要なセクションで使用したり、長い配列(特に、配列の.lengthサイズがchunk-sizeよりも大きい場合n)で使用したりしないでください。これが(JavaScriptとは異なり)遅延言語である場合、このアルゴリズムはO(N ^ 2)時間の影響を受けません。つまり、再帰的な実装はエレガントです。最初にで再帰するヘルパー関数を定義しarray,position、次にディスパッチすることにより、パフォーマンスを改善するために変更することができArray.prototype.chunkます。次に、[[ヘルパー関数](...)を返します
ninjagecko

今夜、私が叫んだにちがいないあなたの精神で私を祝福してくださったsensaiに感謝します
かまれ

1
または...var chunk = (arr, n) => { if ( !arr.length ) return []; return [ arr.slice( 0, n ) ].concat( chunk(arr.slice(n), n) ) }
エドウィリアムズ

28

現在、lodashのチャンク関数を使用して配列を小さな配列に分割できますhttps://lodash.com/docs#chunkループをいじる必要はもうありません!


3
私はSO javascriptの質問に対する免責事項があるはずだと思います:あなたはlodashを試しましたか?私がノードまたはブラウザに含める最初のことのほとんど。
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
この質問に対するほとんどすべてのジェネレータを使用しているか、より複雑な方法でそれらを使用していたという回答に驚いた。このソリューションでの簡潔さとパフォーマンス。
キース

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で単純な非変異型ソリューションを作成することを目指しました。JavaScriptの特殊性により、マッピング前に空の配列を埋める必要があります:-(

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 2018

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悪い、私はそこにコメントを追加しなかった。sliceTypedArraysubarray
ええ

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 [0..1]のサブ配列をaから削除し、サブ配列a [0..1]を返します。私はこれらすべての配列の配列を作成しています
Arpit Jain

2
splice()の代わりに非破壊的なslice()メソッドを使用することをお勧めします
Ash Blue

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

1
なぜこれが反対票が投じられたのかはわかりませんが、コードはいくつかの説明を使用できます。
jpaugh 2017

2
スプライスは元の配列を破壊するためです。
メタリム2017

7

次のES2015アプローチは、関数を定義することなく、匿名配列で直接機能します(チャンクサイズ2の例)。

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

このための関数を定義したい場合は、次のように行うことができます(K._のBlazemongerの回答に関するコメントを改善)。

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



5

使用するもう1つの解決策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によるソリューションと非常によく似ています。ただし、このソリューションは配列拡散を利用せず、reduce関数で新しい配列を作成しないため、他のソリューションよりも高速で(jsPerfテストを参照)、主観的に読みやすく(単純な構文)です。

n回ごとの反復(n = size;最初の反復から開始)では、アキュムレータ配列(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
}

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


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.