0

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.

4
  • 1
    Please post your best attempt at solving it. Commented Jan 3, 2022 at 21:39
  • Once you've chunked each nested array, you should be able to loop through them and concatenate corresponding elements of each. Commented Jan 3, 2022 at 21:40
  • Will the lenght of the outer array also be divisible by the chunk size? Commented Jan 3, 2022 at 22:07
  • 1
    @pilchard Yes sorry for the initial confusion, I have updated the question. the initial array will always be divisible buy the chunk size. my chunk size is 20 but the chunk size here for an example is 3 for easy of examples. Commented Jan 3, 2022 at 22:09

2 Answers 2

1

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(', ')));

Sign up to request clarification or add additional context in comments.

5 Comments

The issue with this is if the array have more lines for example 6 it will get all the first 3 values and push them into result[0] I will update my question, sorry.
Edited. It's still just chunk/zip, but you need to chunk the outer array first.
Amazing, thank you. I'm just going to pop in a huge array in JSFIddle and update the chunk size to see if it works nicely.
I have run a sample of 40k data points and this works amazingly.
Glad it helped. Read through the linked questions, there are other options for each utility including implementations using generator functions that may be more efficient on larger inputs.
0

You can do it with a nested loop, slicing the array each time based on the size of the outer array.

const arr = [
   [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]
];

let out = [];
for(let i in arr) { out.push([]);}

arr.forEach((e, i) => {
    let scale = e.length / arr.length;
    for(let j in arr)
    {
      out[j] = out[j].concat(e.slice(j * scale, j * scale + scale));
    }
});

console.log(out);

Here it is once more with your original array prior to your edit:

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

let out = [];
for(let i in arr) { out.push([]);}

arr.forEach((e, i) => {
    let scale = e.length / arr.length;
    for(let j in arr)
    {
      out[j] = out[j].concat(e.slice(j * scale, j * scale + scale));
    }
});

console.log(out);

3 Comments

The only issue with this answer is if the array has more than one 3 lines, for example, if it has 6 the last 3 arrays from the output are empty. jsfiddle.net/zpLyg7xf
My original answer assumed that your array had dimensions of [i][i^2]. I've updated my answer so it will now work as long as the dimensions are [i][i*n]. The behavior is undefined if the inner array length is not divisible by the outer array length.
Your question has changed so significantly since your original post that it may be worth asking a new question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.