web-dev-qa-db-ja.com

配列をチャンクに分割する

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

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

最大で10個の要素を使用して、配列を多数の小さな配列にチャンク(分割)するにはどのような方法が適切でしょうか。

379
Industrial

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
}
505
Blazemonger

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

デモ:

> [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の方法と同じです)。

より効率的な方法:

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;
    }
});
// refresh page if experimenting and you already defined Array.prototype.chunk

最近の私の好ましい方法は、上記のもの、または以下のうちの1つです。

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

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

プロトタイプを安全に拡張する方法はありますが(すべてのブラウザではそうではありません)、拡張プロトタイプから作成されたオブジェクトを安全に消費する方法がありますが、もっとよい経験則は Principle of Least Surprise に従うことです。完全に練習します。

時間がある場合は、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;
82
furf

これはreduceを使ったES6バージョンです。

perChunk = 2 // items per chunk    

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

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

// 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
}, [])
61
Andrei R

私はjsperf.comに異なった答えをテストしました。結果はそこにあります: http://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;
}
32
AymKdn

splice methodを使いたいのですが。

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

古い質問:新しい答え!私は実際にこの質問からの答えで作業していて、それを友達に改善させました!だからここにあります:

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

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))
23
Shairon Toledo

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

21

さて、かなりタイトなものから始めましょう:

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

私は純粋な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のとんでもないほど弱い配列関数は良いパズルになります:-)

9
thoredge

私はこれが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));
8

EcmaScriptバージョン> = 5.1を使用する場合、 array.reduce() を使用してchunk()の機能バージョンを実装できます。これはO(N)の複雑さを持ちます。

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

グローバルなArrayオブジェクトにchunk()関数を追加することができます。

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
matsev
results = []
chunk_size = 10
while(array.length > 0){
   results.Push(array.splice(0, chunk_size))
}
7
Jon
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 ] ]
7
Arpit Jain

多くの答えがありましたが、これは私が使っているものです:

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, 4]]
// 1: [[1, 2, 3, 4]]
// 2: [[1, 2, 3, 4]]
// 3: [[1, 2, 3, 4]]
// 4: [[1, 2, 3, 4], [5, 6, 7, 8]]
// 5: [[1, 2, 3, 4], [5, 6, 7, 8]]
// 6: [[1, 2, 3, 4], [5, 6, 7, 8]]
// 7: [[1, 2, 3, 4], [5, 6, 7, 8]]
// 8: [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]
// 9: [[1, 2, 3, 4], [5, 6, 7, 8], [9, 10]]
7
Steve Holgado

このためのnpmパッケージを作成しました https://www.npmjs.com/package/array.chunk

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

  return result;
6
zhiyelee

これが私のこのトピックへの貢献になります。 .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
Redu

Array.prototypereduceおよびPushメソッドに基づくES6の1行アプローチ

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
dhilt

これは私が考えることができる最も効率的で直接的な解決策です。

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

ES6 ジェネレータ version

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

これは再帰と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/ /

2
Suhair Zain

ジェネレータを使う

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]
[...chunks(someArray, 2)] // [[0,1],[2,3],[4,5],[6,7],[8,9]]
2
Ikechukwu Eze

編集:私が書いている間に@ 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
dentaku

次の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)
2
user1460043

これは、多くの数学的な複雑さを伴わずに簡単な答えになるはずです。

function chunkArray(array, sizeOfTheChunkedArray) {
  const chunked = [];

  for (let element of array) {
    const last = chunked[chunked.length - 1];

    if(!last || last.length === sizeOfTheChunkedArray) {
      chunked.Push([element])
    } else {
      last.Push(element);
    }
  }
  return chunked;
}
1
John Doe

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

こんにちはこれを試してください -

 function split(arr, howMany) {
        var newArr = []; start = 0; end = howMany;
        for(var i=1; i<= Math.ceil(arr.length / howMany); i++) {
            newArr.Push(arr.slice(start, end));
            start = start + howMany;
            end = end + howMany
        }
        console.log(newArr)
    }
    split([1,2,3,4,55,6,7,8,8,9],3)
1
M3ghana

これが私のコーヒーリストリスト内包表記を使ったアプローチです。 Coffeescriptの内包表記を詳述した素晴らしい記事は ここで見つけることができます

chunk: (arr, size) ->
    chunks = (arr.slice(index, index+size) for item, index in arr by size)
    return chunks
1
pymarco

これはchunk()関数のきちんと最適化された実装です。デフォルトのチャンクサイズを10と仮定します。

var chunk = function(list, chunkSize) {
  if (!list.length) {
    return [];
  }
  if (typeof chunkSize === undefined) {
    chunkSize = 10;
  }

  var i, j, t, chunks = [];
  for (i = 0, j = list.length; i < j; i += chunkSize) {
    t = list.slice(i, i + chunkSize);
    chunks.Push(t);
  }

  return chunks;
};

//calling function
var list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
var chunks = chunk(list);
1
Mohan Dere

これが、末尾呼び出しの最適化である再帰的なソリューションです。

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]))
1
Chris Vouga

BlazeMongerをjQueryオブジェクト用に少し変更しました。

var $list = $('li'),
    $listRows = [];


for (var i = 0, len = $list.length, chunk = 4, n = 0; i < len; i += chunk, n++) {
   $listRows[n] = $list.slice(i, i + chunk);
}
1
nevace

これはgroupBy関数を使って書いたばかりです。

// utils
const group = (source) => ({
  by: (grouping) => {
    const groups = source.reduce((accumulator, item) => {
      const name = JSON.stringify(grouping(item));
      accumulator[name] = accumulator[name] || [];
      accumulator[name].Push(item);
      return accumulator;
    }, {});

    return Object.keys(groups).map(key => groups[key]);
  }
});

const chunk = (source, size) => group(source.map((item, index) => ({ item, index })))
.by(x => Math.floor(x.index / size))
.map(x => x.map(v => v.item));


// 103 items
const arr = [6,2,6,6,0,7,4,9,3,1,9,6,1,2,7,8,3,3,4,6,8,7,6,9,3,6,3,5,0,9,3,7,0,4,1,9,7,5,7,4,3,4,8,9,0,5,1,0,0,8,0,5,8,3,2,5,6,9,0,0,1,5,1,7,0,6,1,6,8,4,9,8,9,1,6,5,4,9,1,6,6,1,8,3,5,5,7,0,8,3,1,7,1,1,7,6,4,9,7,0,5,1,0];

const chunks = chunk(arr, 10);

console.log(JSON.stringify(chunks));
1
Chris Martin

私はあなたの質問に対する私のアプローチを示すためにJSFiddleを作成しました。

(function() {
  // Sample arrays
  var //elements = ["0", "1", "2", "3", "4", "5", "6", "7"],
      elements = ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12", "13", "14", "15", "16", "17", "18", "19", "20", "21", "22", "23", "24", "25", "26", "27", "28", "29", "30", "31", "32", "33", "34", "35", "36", "37", "38", "39", "40", "41", "42", "43"];

  var splitElements = [],
      delimiter = 10; // Change this value as needed
      
  // parameters: array, number of elements to split the array by
  if(elements.length > delimiter){
        splitElements = splitArray(elements, delimiter);
  }
  else {
        // No need to do anything if the array's length is less than the delimiter
        splitElements = elements;
  }
  
  //Displaying result in console
  for(element in splitElements){
        if(splitElements.hasOwnProperty(element)){
        console.log(element + " | " + splitElements[element]);
    }
  }
})();

function splitArray(elements, delimiter) {
  var elements_length = elements.length;

  if (elements_length > delimiter) {
    var myArrays = [], // parent array, used to store each sub array
      first = 0, // used to capture the first element in each sub array
      index = 0; // used to set the index of each sub array

    for (var i = 0; i < elements_length; ++i) {
      if (i % delimiter === 0) {
        // Capture the first element of each sub array from the original array, when i is a modulus factor of the delimiter.
        first = i;
      } else if (delimiter - (i % delimiter) === 1) {
      // Build each sub array, from the original array, sliced every time the i one minus the modulus factor of the delimiter.
        index = (i + 1) / delimiter - 1;
        myArrays[index] = elements.slice(first, i + 1);
      }
      else if(i + 1 === elements_length){
        // Build the last sub array which contain delimiter number or less elements
        myArrays[index + 1] = elements.slice(first, i + 1);
      }
    }
    // Returned is an array of arrays
    return myArrays;
  }
}

まず第一に、私は2つの例を持っています:8つより少ない要素を持つ配列、8つより多くの要素を持つ配列を持つもの(あなたが使いたくないものはコメント).

それから配列のサイズをチェックします。単純ですが余分な計算を避けるために不可欠です。ここから配列が基準を満たす場合(配列サイズ> delimiter)、splitArray関数に移ります。

splitArray関数はデリミタ(8を意味します、それはあなたが分割したいものなので)と配列それ自身を取ります。配列の長さを再利用しているので、firstlastと同様に変数にキャッシュしています。

firstは、配列内の最初の要素の位置を表します。この配列は8つの要素からなる配列です。したがって、最初の要素を決定するために、係数演算子を使用します。

myArraysは配列の配列です。その中に、各インデックスに、サイズ8以下の任意のサブ配列を格納します。これが以下のアルゴリズムの重要な戦略です。

indexは、myArrays変数のインデックスを表します。 8要素以下のサブ配列を格納するたびに、対応するインデックスに格納する必要があります。したがって、27個の要素がある場合、それは4つの配列を意味します。 1番目、2番目、3番目の配列はそれぞれ8つの要素を持ちます。最後の要素は3つだけです。そのためindexはそれぞれ0、1、2、3になります。

トリッキーな部分は単純に数学を考え出し、それを可能な限り最適化することです。例えばelse if (delimiter - (i % delimiter) === 1)これは、配列が一杯になるときに、配列内の最後の要素を見つけることです(例:10個の要素を含む)。

このコードはすべてのシナリオで機能します。delimiterを任意の配列サイズに合わせて変更することもできます。すごくいいね:-)

質問は?下記のコメント欄にお気軽にお問い合わせください。

1
AGE

私はスライスの代わりにスプライス法を使うのが好きです。このソリューションでは、配列の長さとチャンクサイズを使用してループカウントを作成してから、各ステップでスプライシングが行われるため、操作ごとに小さくなる配列をループします。

    function chunk(array, size) {
      let resultArray = [];
      let chunkSize = array.length/size;
      for(i=0; i<chunkSize; i++) {
        resultArray.Push(array.splice(0, size));
      }
    return console.log(resultArray);
    }
    chunk([1,2,3,4,5,6,7,8], 2);

元の配列を変更したくない場合は、spread演算子を使用して元の配列を複製してから、その配列を使用して問題を解決できます。

    let clonedArray = [...OriginalArray]
0
SeaWarrior404

私は完全に私のために働いたのと同じ目的のために次のように使いました。これが誰かに役立つことを願っています

private byte[][] ByteArrayToChunks(byte[] byteData, long BufferSize)
{
    byte[][] chunks = byteData.Select((value, index) => new { PairNum = Math.Floor(index / (double)BufferSize), value }).GroupBy(pair => pair.PairNum).Select(grp => grp.Select(g => g.value).ToArray()).ToArray();
    return chunks;
}
0
Jack Gajanan

純粋なjsを使ったさらに別の解決策XD。

let numbers = [1,2,3,4,5,6,7,8]; // Initial values

let groups = []; // The grouped values
let group = 0; // Group Index
let split = 3; // I will split in groups of 3 items

for(let i = 0, length = numbers.length; i < length; i++) {
    if (Math.floor(i / split) !== group) {
        //I need a new group in this case, so I make a new index
        group += 1;
    }
    if (!groups[group]) {
        //If I don't have the group of this index, create a new group array
        groups[group] = [];
    }
    //I add the numbers or letters to the group
    groups[group].Push(numbers[i]);
}
console.log(groups);

そして、これはより洗練された解決策で、分割されたグループと同じサイズのステップを持つforを使っています。

// Another options more elegant:
let numbers = [1,2,3,4,5,6,7,8]; // Initial values
let groups2 = []; // The grouped values
let split = 3;
for(let i = 0, j = 0, length = numbers.length; i < length; i+=split, j++) {
    groups2[j] = numbers.slice(i, i + split);
}

あなたは再利用のための関数を使うことができます... 3の分割の結果は以下のとおりです。

[[1、2、3]、[4、5、6]、[7、8]]

2分割の場合は、次のとおりです。

[[1、2]、[3、4]、[5、6]、[7、8]]

最初の数字のセットは壊れません。

これがフィドルです。

Fiddle example

0
juan garcia

他の例とは少し異なりますが、 reduce() メソッドを使った別の解決策があります。うまくいけば、私の説明も少し明確になります。

var arr = [0, 1, 2, 3, 4, 5, 6, 7];
var chunkSize = 3;

arr = arr.reduce((acc, item, idx) => {
  let group = acc.pop();
  if (group.length == chunkSize) {
    acc.Push(group);
    group = [];
  }
  group.Push(item);
  acc.Push(group);
  return acc;
}, [[]]);

console.log(arr); //Prints [[0, 1, 2], [3, 4, 5], [6, 7]]

説明

配列の各項目に対して、pop()を使ってアキュムレータの最後の項目を取得するリデューサーを呼び出します。この項目はchunkSize個の項目までグループ化する配列です(この例では3)。

このグループの配列長がchunksizeに等しい場合に限り、そのグループをアキュムレータに再挿入して新しいグループを作成する必要があります。

次に、現在のitemgroup配列(前のステップの0、1、または2項目が既に含まれている場合がある)にプッシュします。現在のitemgroupに挿入したら、groupをより大きなコレクションに再挿入する必要があります。

このプロセスは、arr内のすべての項目を反復処理するまで繰り返されます。

[[]]を使用して、配列内の空の配列の開始値をリデューサーにも提供したことに注意してください。

0
Chris

彼女は@Blazemongerソリューションを使用したシンプルなソリューションです

function array_chunk(arr, size){
    // initialize vars
    var i,
    j = arr.length,
    tempArray = [];
    // loop through and jump based on size
    for (i=0; i<j; i+=size) {
        // slice chunk of arr and Push to tempArray
        tempArray.Push(arr.slice(i,i+size));
    }
    // return temp array (chunck)
    return tempArray
}

これは私にピップラインを流しました。これが他の誰かに役立つことを願っています。 :)

0
Daniel Barde

機能的な解決策の場合は、 Ramda を使用します。

popularProductsが入力配列の場合、5はチャンクサイズです。

import splitEvery from 'ramda/src/splitEvery'

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

})
0
Damian Green

私のトリックはparseInt(i/chunkSize)parseInt(i%chunkSize)を使い、それから配列を埋めることです

// filling items
let array = [];
for(let i = 0; i< 543; i++)
  array.Push(i);
 
 // printing the splitted array
 console.log(getSplittedArray(array, 50));
 
 // get the splitted array
 function getSplittedArray(array, chunkSize){
  let chunkedArray = [];
  for(let i = 0; i<array.length; i++){
    try{
      chunkedArray[parseInt(i/chunkSize)][parseInt(i%chunkSize)] = array[i];
    }catch(e){
      chunkedArray[parseInt(i/chunkSize)] = [];
      chunkedArray[parseInt(i/chunkSize)][parseInt(i%chunkSize)] = array[i];
    }
  }
  return chunkedArray;
 }
0
NuOne
# in coffeescript
# assume "ar" is the original array
# newAr is the new array of arrays

newAr = []
chunk = 10
for i in [0... ar.length] by chunk
   newAr.Push ar[i... i+chunk]

# or, print out the elements one line per chunk
for i in [0... ar.length] by chunk
   console.log ar[i... i+chunk].join ' '
0
Patrick Chu

これを試して :

var oldArray =  ["Banana", "Orange", "Lemon", "Apple", "Mango", "Banana", "Orange", "Lemon", "Apple", "Mango", "Banana", "Orange", "Lemon", "Apple", "Mango", "Banana", "Orange", "Lemon", "Apple", "Mango", "Banana", "Orange", "Lemon", "Apple", "Mango"];

var newArray = [];

while(oldArray.length){
    let start = 0;
    let end = 10;
    newArray.Push(oldArray.slice(start, end));
    oldArray.splice(start, end);
 }
 
 console.log(newArray);
0
Harunur Rashid

これは末尾再帰と配列デストラクタリングを含むバージョンです。

最速のパフォーマンスからはほど遠い しかし、jsが今すぐこれを実行できることを嬉しく思います。最適化されていなくても:(

const getChunks = (arr, chunk_size, acc = []) => {
    if (arr.length === 0) { return acc }
    const [hd, tl] = [ arr.slice(0, chunk_size), arr.slice(chunk_size) ]
    return getChunks(tl, chunk_size, acc.concat([hd]))
}

// USAGE
const my_arr = [1,2,3,4,5,6,7,8,9]
const chunks = getChunks(my_arr, 2)
console.log(chunks) // [[1,2],[3,4], [5,6], [7,8], [9]]
0
AaronCoding

これはImmutableJSを使った解決策です。ここでitemsは不変リストで、sizeは必要なグループ化サイズです。

const partition = ((items, size) => {
  return items.groupBy((items, i) => Math.floor(i/size))
})
0
taylor