Search code examples
javascriptarrayschunking

Chunk data from array of arrays


Before marking this as answered by another question please note this is an array of arrays, not a flat array, also, the number I have given are an example, I have just shown them so you can visually see what is happening.

I am trying to loop through an array of arrays. I have the following array:-

[
   [1, 2, 3, 4, 5, 6, 7, 8, 9],
   [1, 2, 3, 4, 5, 6, 7, 8, 9],
   [1, 2, 3, 4, 5, 6, 7, 8, 9],
   [3, 2, 1, 6, 5, 4, 9, 8, 7],
   [6, 5, 4, 9, 8, 7, 3, 2, 1],
   [7, 8, 9, 3, 2, 1, 6, 5, 4]
]

How is it possible to transform this array into chunks of 3x3 for example:-

[
   [1, 2, 3, 1, 2, 3, 1, 2, 3],
   [4, 5, 6, 4, 5, 6, 4, 5, 6],
   [7, 8, 9, 7, 8, 9, 7, 8, 9],
   [3, 2, 1, 6, 5, 4, 9, 8, 7],
   [6, 5, 4, 9, 8, 7, 3, 2, 1],
   [7, 8, 9, 3, 2, 1, 6, 5, 4],
]

As you can see from the array above I have chunked it using the first 3 values from each array and then by the 2nd 3n from each array and lastly the final 3n from each array.

So the array would be chunked like the following:-

1 2 3 | 4 5 6 | 7 8 9
1 2 3 | 4 5 6 | 7 8 9
1 2 3 | 4 5 6 | 7 8 9
---------------------
3 2 1 | 6 5 4 | 9 8 7
6 5 4 | 9 8 7 | 3 2 1
7 8 9 | 3 2 1 | 6 5 4

I have tried to loop through each line and resetting the column count when it hits an increment and increasing the row but this didn't work.

I can update the question with previous attempts if this is of any help? Also just a note, the array will be different sizes but always divisible by a particular number, for the above example I have chosen the number 3.

I have updated the question with more information. The array of arrays will always be divisible by a specific number, this example shows a divisible number of 3.


Solution

  • This can be solved with a chunk as per this question Split array into chunks combined with a zip as per this Javascript equivalent of Python's zip function

    This has the benefit of being able to reverse the operation to get back to the original.

    /** @see: https://stackoverflow.com/questions/8495687/split-array-into-chunks */
    function chunk(array, chunk) {
        let result = [];
        for (let i = 0; i < array.length; i += chunk) {
            result.push(array.slice(i, i + chunk));
        }
        return result;
    }
    
    /** @see: https://stackoverflow.com/questions/4856717/javascript-equivalent-of-pythons-zip-function */
    function zip(...rows) {
        return [...rows[0]].map((_, c) => rows.map((row) => row[c]));
    }
    
    const array = [
        [1, 2, 3, 4, 5, 6, 7, 8, 9],
        [1, 2, 3, 4, 5, 6, 7, 8, 9],
        [1, 2, 3, 4, 5, 6, 7, 8, 9],
        [3, 2, 1, 6, 5, 4, 9, 8, 7],
        [6, 5, 4, 9, 8, 7, 3, 2, 1],
        [7, 8, 9, 3, 2, 1, 6, 5, 4],
    ];
    
    const result = chunk(array, 3)
        .flatMap((innerChunk) =>
            zip(...innerChunk.map((arr) => chunk(arr, 3)))
            .map((arr) => arr.flat())
        );
    
    console.log(result.map((a) => a.join(', ')));
    
    // Allows the result to be reverted to the original
    const reversed = chunk(result, 3)
        .flatMap((innerChunk) =>
            zip(...innerChunk.map((arr) => chunk(arr, 3)))
            .map((arr) => arr.flat())
        );
    
    console.log(reversed.map((a) => a.join(', ')));