Saif Warsi
Saif Warsi

Reputation: 338

How to calculate average in Angular using json data

import {
  Component,
  OnInit
} from "@angular/core";
import {
  MarkService
} from "../app/services/marks.service";

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.scss"]
})
export class AppComponent implements OnInit {
  title = "my-test";
  public students = [];
  allStudents: any = [];
  average: any = [];

  constructor(private _marksService: MarkService) {}

  ngOnInit() {
    this._marksService.getMarks().subscribe(data => (this.students = data));
  }

  calHandle(i) {
    var data = this.students;
    this.average = Object.values(data).reduce(
      (avg, {
        values
      }, _, {
        length
      }) => avg + values / length,
      0
    );
  }
}
<table border="1">
  <tr>
    <th>Name</th>
    <th>Jan</th>
    <th>Feb</th>
    <th>March</th>
    <th>April</th>
    <th>action</th>
    <th>Average</th>
    <!-- </tr> -->
    <tbody *ngFor="let item of students; let i = index;">
      <tr>
        <td>{{item.name}}</td>
        <td>{{item.jan}}</td>
        <td>{{item.feb}}</td>
        <td>{{item.march}}</td>
        <td>{{item.April}}</td>
        <td><button (click)="calHandle(i)">calculate</button></td>
        <td>{{average}}</td>
      </tr>
    </tbody>

</table>

<!--
json data

[
 {"name": "josh", "jan":20,"feb":32, "march":"50", "April":45},
 {"name": "peter", "jan":20,"feb":32, "march":"50", "April":45},
 {"name": "gorge", "jan":20,"feb":32, "march":"50", "April":45}
]

-->

Above is my snippet for calculating the average of students on click event but whenever I am clicking on the button "calculate" the result I am getting is "NaN" so I am a little bit unsure that how do I provide only number value to prevent "NaN" error and what should I do for getting average of a particular student on button click.

Upvotes: 1

Views: 2700

Answers (2)

Adrita Sharma
Adrita Sharma

Reputation: 22213

Try like this:

.ts

calHandle(i: number) {
    var sum = 0;
    var keys = Object.keys(this.students[i]);
    keys.forEach(key => {
      if (key != "name") {
        sum += Number(this.students[i][key]);
      }
    });
    this.students[i].average = sum / (keys.length - 1);
}

.html

<table border="1">
  <tr>
    <th>Name</th>
    <th>Jan</th>
    <th>Feb</th>
    <th>March</th>
    <th>April</th>
    <th>action</th>
    <th>Average</th>
    </tr>
    <tbody *ngFor="let item of students; let i = index;">
      <tr>
        <td>{{item.name}}</td>
        <td>{{item.jan}}</td>
        <td>{{item.feb}}</td>
        <td>{{item.march}}</td>
        <td>{{item.April}}</td>
        <td><button (click)="calHandle(i)">calculate</button></td>
        <td>{{item.average}}</td>
      </tr>
    </tbody>
</table>

Working Demo

Upvotes: 2

shrys
shrys

Reputation: 5940

You could use Object.entries to check the key of your object and omit it if it is 'name':

const result = [
 {"name": "josh", "jan":20,"feb":32, "march":"50", "April":45},
 {"name": "peter", "jan":20,"feb":32, "march":"50", "April":45},
 {"name": "gorge", "jan":20,"feb":32, "march":"50", "April":45}
].map(getAverage);

function getAverage(obj) {
  return Object.entries(obj).reduce((avg, obj, _, { length }) => obj[0] == 'name' ? avg : avg + obj[1] / length, 0);
}


console.log(result);

So in your case it would be:

calHandle(i) {
  var data = this.students;
  this.average = Object.entries(data).reduce(
    (avg, obj, _, {
      length
    }) => obj[0] == 'name' ? avg : avg + obj[1] / length,
    0
  );
}

Upvotes: 0

Related Questions