I have a problem with populating an array based on another array.
It seems when I push a value onto a specific index in the array, it is populating all indexes.
Code
import { Component, VERSION } from '@angular/core';
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent {
name = 'Angular ' VERSION.major;
public matrix: number[] = [
1, 2, 3, 4, 5, 6, 7, 8, 9.1, 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, 44, 45,
];
public matrixColumns: number[][] = [];
public expectedMatrixColumns: number[][] = [
[1, 10, 19, 28, 37],
[2, 11, 20, 29, 38],
[3, 12, 21, 30, 39],
[4, 13, 22, 31, 40],
[5, 14, 23, 32, 41],
[6, 15, 24, 33, 42],
[7, 16, 25, 34, 43],
[8, 17, 26, 35, 44],
[9, 18, 27, 36, 45],
];
public numberofColumns: number = 9;
columnStartIndex: number = 0;
constructor() {
this.createColumnMatrix();
}
createColumnMatrix() {
let columnsMatrix = [];
let numberRows = this.matrix.length / this.numberofColumns;
let matrixIndex = 0;
for (let index = 0; index < this.numberofColumns; index ) {
this.matrixColumns.push([]);
}
let columnIndex: number = 0;
this.matrix.forEach((number, matrixIndex) => {
debugger;
this.matrixColumns[columnIndex].push(this.matrix[matrixIndex]);
debugger;
matrixIndex = matrixIndex 1;
columnIndex = columnIndex 1;
if (columnIndex > this.numberofColumns - 1) {
columnIndex = 0;
}
});
}
}
Demo Project
Here is a JavaScript version that reproduces the problem:
class AppComponent {
matrix = [
1, 2, 3, 4, 5, 6, 7, 8, 9.1, 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, 44, 45,
];
matrixColumns = [];
expectedMatrixColumns = [
[1, 10, 19, 28, 37],
[2, 11, 20, 29, 38],
[3, 12, 21, 30, 39],
[4, 13, 22, 31, 40],
[5, 14, 23, 32, 41],
[6, 15, 24, 33, 42],
[7, 16, 25, 34, 43],
[8, 17, 26, 35, 44],
[9, 18, 27, 36, 45],
];
numberofColumns = 9;
columnStartIndex = 0;
constructor() {
this.createColumnMatrix();
}
createColumnMatrix() {
let columnsMatrix = [];
let numberRows = this.matrix.length / this.numberofColumns;
let matrixIndex = 0;
for (let index = 0; index < this.numberofColumns; index ) {
this.matrixColumns.push(columnsMatrix);
}
let columnIndex = 0;
this.matrix.forEach((number, matrixIndex) => {
this.matrixColumns[columnIndex].push(this.matrix[matrixIndex]);
matrixIndex = matrixIndex 1;
columnIndex = columnIndex 1;
if (columnIndex > this.numberofColumns - 1) {
columnIndex = 0;
}
});
}
}
let component = new AppComponent();
for (let row of component.matrixColumns) {
console.log(JSON.stringify(row));
}
Problem
If you look at this line in the code:
this.matrixColumns[columnIndex].push(this.matrix[matrixIndex]);
It is pushing the first value in the array (matrix which is 1), into every index in my second array matrixColumns
.
Expected output
[1, 10, 19, 28, 37]
[2, 11, 20, 29, 38]
[3, 12, 21, 30, 39]
[4, 13, 22, 31, 40]
[5, 14, 23, 32, 41]
[6, 15, 24, 33, 42]
[7, 16, 25, 34, 43]
[8, 17, 26, 35, 44]
[9, 18, 27, 36, 45]
Actual output
[1,2,3,4,5,6,7,8,9.1,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,44,45]
[1,2,3,4,5,6,7,8,9.1,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,44,45]
[1,2,3,4,5,6,7,8,9.1,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,44,45]
[1,2,3,4,5,6,7,8,9.1,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,44,45]
[1,2,3,4,5,6,7,8,9.1,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,44,45]
[1,2,3,4,5,6,7,8,9.1,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,44,45]
[1,2,3,4,5,6,7,8,9.1,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,44,45]
[1,2,3,4,5,6,7,8,9.1,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,44,45]
[1,2,3,4,5,6,7,8,9.1,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,44,45]
CodePudding user response:
you can do something like this
const buildMatrix = (data, columns) => data.reduce((res, d, i) => {
const row = i % columns
const rowData = [...(res[row] || []), d]
res[row] = rowData
return res
}, [])
const data = [
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, 44, 45,
];
const matrix = buildMatrix(data, 9)
console.log(matrix)
CodePudding user response:
you need two dimensions something like
this.matrixColumns[columnIndex][matrixIndex].push(this.matrix[columnIndex][matrixIndex]);
CodePudding user response:
The problem is that you only have one columnsMatrix
array. After pushing its reference to this.matrixColumns
repeatedly, you end up with multiple references to the same array. So whether you then push to this.matrixColumns[0]
or to this.matrixColumns[1]
doesn't make a difference, ... you're always pushing to the same array.
You can solve this by pushing a new array unto this.matrixColumns
at every call of push
.
So replace:
this.matrixColumns.push(columnsMatrix);
with:
this.matrixColumns.push([]);
Simplified code
Not your question, but you can do this as follows:
this.matrixColumns = Array.from({length: this.numberofColumns}, (_, i) =>
Array.from({length: numberRows}, (_, j) => matrix[i j*numberRows])
);
let matrix = [
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, 44, 45,
];
let numberofColumns = 9;
let numberofRows = Math.ceil(matrix.length / numberofColumns);
// logic
let matrixColumns = Array.from({length: numberofColumns}, (_, i) =>
Array.from({length: numberofRows}, (_, j) => matrix[i j*numberofRows])
);
// display
for (const row of matrixColumns) console.log(JSON.stringify(row));