convert 9x9 array into 9 (3x3) array in javascript? i have written the code, but its not pushing the 3x3's into separate array. i want 9 3x3 arrays
let array =
[
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[2, 3, 1, 5, 6, 4, 8, 9, 7],
[3, 1, 2, 6, 4, 5, 9, 7, 8],
[4, 5, 6, 7, 8, 9, 1, 2, 3],
[5, 6, 4, 8, 9, 7, 2, 3, 1],
[6, 4, 5, 9, 7, 8, 3, 1, 2],
[7, 8, 9, 1, 2, 3, 4, 5, 6],
[8, 9, 7, 2, 3, 1, 5, 6, 4],
[9, 7, 8, 3, 1, 2, 6, 4, 5]
];
let final=[];
let row = [0,1,2];
let col = [0,1,2];
let counter = 0;
for ( let i = 0 ; i <= array.length - 1 ; i += 3 )
{
for(let j = 0 ; j <= array.length - 1 ; j += 3 )
{
final.push([]);
row.forEach( ele1 => {
final[counter].push([])
col.forEach( ele2 => {
final[counter][ele1].push(array[ele1+i][ele2+j]);
})
})
counter+=1;
}
}
console.log(final)
You can loop through the array using map function and check for the index values to break into arrays as required.
let myArr =[[1, 2, 3, 4, 5, 6, 7, 8, 9],
[2, 3, 1, 5, 6, 4, 8, 9, 7],
[3, 1, 2, 6, 4, 5, 9, 7, 8],
[4, 5, 6, 7, 8, 9, 1, 2, 3],
[5, 6, 4, 8, 9, 7, 2, 3, 1],
[6, 4, 5, 9, 7, 8, 3, 1, 2],
[7, 8, 9, 1, 2, 3, 4, 5, 6],
[8, 9, 7, 2, 3, 1, 5, 6, 4],
[9, 7, 8, 3, 1, 2, 6, 4, 5]];
let newArr = convertTo3x3(myArr);
console.log(newArr);
function convertTo3x3(myArr){
let array3x3 = [];
myArr.map((row, rIndex) => {
let tempArr = [];
let row3 = [];
row.map((item, lIndex) => {
// convert each row to 3x3 rows
if(lIndex % 3 == 0){
// reset row3 for new 3x3 arr on every 1st item of 3x3
row3 = [];
}
row3.push(item);
if(lIndex % 3 == 2){
// push 3x3 row to tempArr on every 3rd item of 3x3
tempArr.push(row3);
}
});
array3x3.push(tempArr);
});
return array3x3;
}
Your code seems to work fine, but if you want a more javascriptey code, that performs worse, here you go.
let array = [
[1, 2, 3, 4, 5, 6, 7, 8, 9],
[2, 3, 1, 5, 6, 4, 8, 9, 7],
[3, 1, 2, 6, 4, 5, 9, 7, 8],
[4, 5, 6, 7, 8, 9, 1, 2, 3],
[5, 6, 4, 8, 9, 7, 2, 3, 1],
[6, 4, 5, 9, 7, 8, 3, 1, 2],
[7, 8, 9, 1, 2, 3, 4, 5, 6],
[8, 9, 7, 2, 3, 1, 5, 6, 4],
[9, 7, 8, 3, 1, 2, 6, 4, 5],
];
let final = [];
array
.reduce((a, c) => {
const chunk = (arr, n) =>
arr.length ? [arr.slice(0, n), ...chunk(arr.slice(n), n)] : [];
return [...a, ...chunk(c, 3)];
}, [])
.map((el, i) => {
if (i % 3 == 0) {
final = [...final, [el]];
} else {
final[Math.floor(i / 3)] = [...final[Math.floor(i / 3)], el];
}
});
console.log(final);
Your code is trying to do too much. Make it difficult to understand.
I would first break it up. Write a simple function than knows how to take an array-of-arrays and return an arbitrary rectangular selection from it. Something like this, that's easy to test:
/**
* Snip a rectangular section of an array of arrays (ragged, 2D array).
* The returned array-of-arrys will ALWAYS be the specified size, padded
* with 'undefined' values to the specified size.
*
* @param {Object[][]} arr - An array of arrays (ragged 2D array)
* @param {number} row - Origin row: {row,col} denotes the upper-left corner of the rectangle to snip
* @param {number} col - Origin column: {row,col} denotes the upper-left corner of the rectangle to snip
* @param {number} nrows - Number of rows to snip
* @param {number} ncols - Nunber of columns to snip
*
* @returns {Object[][]}
*/
function snip(arr, row, col, nrows, ncols ) {
const selection = [];
for ( let r = row, i = 0 ; r < row+nrows ; ++r, ++i ) {
selection[i] = [];
const tmp = arr[r] ?? [];
for ( let c = col, j = 0 ; c < col+ncols ; ++c, ++j ) {
selection[i][j] = tmp[c];
}
}
return selection;
}
Once you have that, then chopping up your larger array-of-arrays into 3x3 arrays is easy.
This code starts at the top left corner or your 9x9 array and returns a flat list containing 9 separate 3x3 arrays, chopped out left-to-right and top-to-bottom:
final = [];
for ( let x = 0 ; x < 9; x += 3 ) {
for ( let y = 0 ; y < 9 ; y += 3 ) {
// (x,y) denotes the top left corner of the desired sub-array
final.push( snip(arr, x,y, 3,3 ) );
}
}
The nice thing about this approach is that it is easy to test, and . . . It's flexible. It can handle a source array of any size, and you can chop it up into subarrays of any size and in any order, whatever you see fit to do.