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.
To do this:
I used reduce to create a dictionary that has each student's grade sum and grade count.
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.
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)
I think that what you want.
sum, counter to count the occurrence of each name, average and avgArr to store the averagesname 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.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]