4

I have an array suppose [1,2,3,4,5,6,7,8,9,10] want to make nxn matrix on html side of angular.

I know I can first divide the array to 2d in typescript file [[1,2,3,4,5],[6,7,8,9,10]] and iterate over elements in html using *ngFor.

But I am trying to find a way to show a matrix using single array in component.html without converting it into 2d array.

output:

1 2 3 4 5
6 7 8 9 10
Zamir
  • 217
  • 2
  • 11
  • Welcome to StackOverflow! Please provide your code where you first tried, and what were the problems yuo've encountered. – Davide Vitali Mar 17 '19 at 09:20
  • Possible duplicate of [Split array into chunks](https://stackoverflow.com/questions/8495687/split-array-into-chunks) – Reactgular Mar 17 '19 at 09:20
  • @cgTag It's not, please read I mentioned I can easily split the array but how to just iterate in Angular html without splitting. – Zamir Mar 17 '19 at 09:28
  • Your question is not really clear to me sorry, could you explain to me what is the goal of your component please? – ale Mar 17 '19 at 09:29
  • 1
    Use a CSS grid. https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_Grid_Layout – Reactgular Mar 17 '19 at 09:31
  • 1
    If you don't want to split the array, you can use CSS layouting to achieve that. No need for any special Angular code. Set the width of the cell containing the value to 1/n the width of the container and use display:inline-block. Better yet, use a flex box. – ethanfar Mar 17 '19 at 09:31
  • nice shot @cgTag, I think is not a math/javascript related question, seems more a design problem – ale Mar 17 '19 at 09:33
  • @ccTag check jo_va answer – Zamir Mar 17 '19 at 10:08
  • @Alessandro check jo_va answer – Zamir Mar 17 '19 at 10:08

3 Answers3

4

If you want to display the matrix in the template without any logic on the typescript side, you could use the Array.prototype.slice to generate an array as long as your number of rows. Then iterate on that array with ngFor and get the index from the index variable, this will be your row index.

Then use an inner ngFor and slice again to get the row from your array and the row index.

You simply have to set n to the number of items per row:

<div *ngFor="let row of arr.slice(0, arr.length / n % 1 === 0 ? arr.length / n : arr.length / n + 1); let idx = index">
  <span *ngFor="let x of arr.slice(idx * n, idx * n + n)">{{ x }}</span>
</div>

See this stackblitz demo.

However, I think a more elegant solution would be to create a matrix from the array in typescript and then simply iterate on the rows and columns:

const arr = [1,2,3,4,5,6,7,8,9,10];
const n = 4;
const matrix = Array
  .from({ length: Math.ceil(this.arr.length / this.n) }, (_, i) => i)
  .map(i => this.arr.slice(i * this.n, i * this.n + this.n));
<div *ngFor="let row of matrix">
  <span *ngFor="let x of row">{{ x }}</span>
</div>

Or you could create that matrix using a pipe in angular, something like this, with a row length of 4:

<div *ngFor="let row of arr | toMatrix:4">
  <span *ngFor="let x of row">{{ x }}</span>
</div>

Then the pipe would hold the logic to create the matrix:

@Pipe({
  name: 'toMatrix'
})
export class ToMatrixPipe implements PipeTransform {
  transform(arr: number[], n: number): number[][] {
    const rows = Array.from({ length: Math.ceil(arr.length / n) }, (_, i) => i);
    return rows.map(idx => arr.slice(idx * n, idx * n + n));
  }
}
jo_va
  • 13,504
  • 3
  • 23
  • 47
  • it's working for sure, but better move the slice logic in the ts (with props) and leave the template live in peace (Y) – ale Mar 17 '19 at 10:19
  • @Alessandro, I absolutely agree with you but the OP wanted to do it on the HTML side. But for sure, I would prefer to do it in the ts and keep the template clean, I will add a warning to the answer – jo_va Mar 17 '19 at 10:21
  • @Zamir, I added an example with a pipe, to move the logic out of the template and make it reusable if needed, you can also check the updated Stackblitz – jo_va Mar 17 '19 at 10:35
  • Thanks @jo_va,I will check.However,after looking above comments ,I just made a function in typescript to convert an array to 2d array to iterate in Html – Zamir Mar 17 '19 at 11:07
  • 1
    @Zamir, that's a good approach, I also added a typescript solution to make the answer more complete – jo_va Mar 17 '19 at 11:15
2

You can achieve it doing the below. I will show both examples, one with 2d array and other with single.

2d Array

var a = [[1,2,3],[4,5,6]];
now to get an element placed at Xth row and Yth column you will use

a[X-1][Y-1]
e.g. to get element form 1st row and 2nd column we will print 

a[1-1][2-1] = a[0][1];

1D Array

var a = [1,2,3,4,5,6];

now to achieve 2D like functionality first define the strength of row.
let that be L. In our case strength of row will be L = 3.

now to get an element placed at Xth row and Yth column you will use
a[Z*(X-1)+ (Y-1)]
e.g. to get element form 1st row and 2nd column we will print 

a[3*(1-1) + (2-1)] = a[1];
Rohini
  • 244
  • 1
  • 8
1

You can simply use % operator.

let nmatrix = (n) => {
  let temp = []
  for(let i=1;i <1+(n*n); i++){
    temp.push(i)
    if(i % n === 0) {
      console.log(...temp)
      temp = []
    }
  }
}


nmatrix(4)
Code Maniac
  • 37,143
  • 5
  • 39
  • 60