Home > Back-end >  Array Of Objects with data of exams submitted, how can I get the average grade of each student in an
Array Of Objects with data of exams submitted, how can I get the average grade of each student in an

Time:07-16

Let's say I have an array of objects that contain information about all the exams submitted during a period of time. It's structure's like this:

[
    { name: 'Freddy', grade: 10, date: '20/07/2022' },
    { name: 'Jose', grade: 8, date:'20/07/2022' },
    { name: 'Freddy, grade: 8', date: '25/07/2022' },
    { name: 'Daniel', grade: 5, date: '21/07/2022' },
    { name: 'Jose', grade: 5 }, date: '22/07/22',
  ]

What I need is to ignore the date value and just calculate the average grade of each student and get a simple array like this:

[9, 6.5, 5]

Now let's say I want the array to follow a specific order so how can I rearrange it following this order: Freddy -> Jose -> Daniel ?

It seems kind of weird but I kind of need the output to be like this in order to use it as a dataset for Chart.js later on.

CodePudding user response:

To do this:

  • I used reduce to create a dictionary that has each student's grade sum and grade count.

    • I used a dictionary because it makes it easy to search through it while reduce iterates through the array.
  • Then I used Object.keys() to get an array of the dictionarie's keys and map-ed that array into an array that has an object for each student's average grade.

    • I did it this way because I assumed that this output could be useful. It would have been simpler to loop over the dictionary and convert it to a dictionary of averages.
  • Then we map the array of objects to just the averages.

const students = [
  { name: 'Freddy', grade: 10, date: '20/07/2022' },
  { name: 'Jose', grade: 8, date:'20/07/2022' },
  { name: 'Freddy', grade: 8, date: '25/07/2022' },
  { name: 'Daniel', grade: 5, date: '21/07/2022' },
  { name: 'Jose', grade: 5 , date: '22/07/22'}
]

const grouped = students.reduce(
  (output, student) => {
    const name = student.name
    if (output[name]) {
      output[name].gradeTotal  = student.grade;
      output[name].count  = 1;
    }
    else {
      output[name] = {
        gradeTotal: student.grade,
        count: 1
      }
    }
   return output
  }, {})

console.log('Grouped by student: ', grouped)

const studentAverages = Object.keys(grouped).map(name => (
   {
    name,
    average: grouped[name].gradeTotal / grouped[name].count 
   }
  )
)

console.log('Student averages: ', studentAverages)

const justAverages = studentAverages.map(student => student.average)

console.log('Just averages:', justAverages)

CodePudding user response:

I think that what you want.

  1. I made some variables for sum, counter to count the occurrence of each name, average and avgArr to store the averages
  2. Then made nested loops. The outer loop to take each object name and store it in the name variable. The inner loop loop through the array, search for the name and calculate the average for each person. Then add this average to the avgArr array.
  3. I added checked property to each object to avoid taking the same object more than one time if it's true skip that object, if the object doesn't have this property take this object, add the checked property and set it to true. If you don't want this property you can remove it later.

let arr =[
    { name: 'Freddy', grade: 10, date: '20/07/2022' },
    { name: 'Jose', grade: 8, date:'20/07/2022' },
    { name: 'Freddy', grade: 8, date: '25/07/2022' },
    { name: 'Daniel', grade: 5, date: '21/07/2022' },
    { name: 'Jose', grade: 5 , date: '22/07/22' }];
    let sum = 0;
    let counter = 0;
    let avg;
    const avgArr = [];
    for (const i of arr){
      let name = i.name;
      if (i.checked === true) {
        continue;
      }
      for (const j of arr){
        if (name === j.name) {
          j.checked = true;
          sum  = j.grade;
          counter  =1;
        }
      }
      avg = sum / counter;                                                        
      avgArr.push(avg);
      sum = counter = 0;    
    }
     console.log(avgArr); // [9, 6.5, 5]

  • Related