Question

There is a great question on how to split a JavaScript array into chunks. I'm currently using this for some statistical methods I'm writing and the answer that I'm using is as follows (although I chose not to extend the Array prototype like they did in the answer):

var chunk = function(array, chunkSize) {
    return [].concat.apply([],
        array.map(function(elem,i) {
            return i%chunkSize ? [] : [array.slice(i,i+chunkSize)];
        })
    );
};

This takes an array, such as [1,2,3,4,5,6], and given a chunkSize of 2 returns [[1,2],[3,4],[5,6]]. I'm curious how I could modify this to create an array of "overlapping" chunks (or for those familiar with methods such as a moving average, "moving subgroups").

Provided the same array as above and chunkSize of 3, it would return [[1,2,3],[2,3,4],[3,4,5],[4,5,6]]. A chunkSize of 2 would return [[1,2],[2,3],[3,4],[4,5],[5,6]].

Any thoughts on how to approach this?

Was it helpful?

Solution

function chunk (array, chunkSize) {
    var retArr = [];
    for (var i = 0; i < array.length - (chunkSize - 1); i++) {
        retArr.push(array.slice(i, i + chunkSize));
    }
    return retArr;
}

If you did want to extend the prototype (probably would be better) it would looks like this:

Array.prototype.chunk = function( chunkSize ) {
    var retArr = [];
    for (var i = 0; i < this.length - (chunkSize - 1); i++) {
        retArr.push( this.slice(i, i + chunkSize));
    }
    return retArr;
}

OTHER TIPS

Using the more declarative and consise (IMO) aproach.

const data = [1,2,3,4,5,6];

function getGroups(dataList, groupSize) {
  return dataList
    .slice(groupSize - 1)
    .map((_, index) => dataList.slice(index, index + groupSize));
}
console.log("2:", JSON.stringify(getGroups(data, 2)));
console.log("3:", JSON.stringify(getGroups(data, 3)));

Firstly I remove the number of elements from the start of the array since number of elements in the output will be appropriately smaller. Then i loop over the remaining elements mapping them to appropriate groups.

I'm not really good with javaScript but this is algorithmically very easy to achieve with two nested for loops. Here is a solution in C# - you should be able to figure this out quite easily.

This used less than optimal data structures and everything but the algorithm itself is obvious.

protected List<List<int>> Split(List<int> array, int chunkSize)
{
    List<List<int>> result = new List<List<int>>();

    for (int i = 0; i < array.Count - chunkSize; i++)
    {
        List<int> temp = new List<int>();
        for (int j = i; j < i + chunkSize; j++)
        {
            temp.Add(array[j]);
        }
        result.Add(temp);
    }

    return result;
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top