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.
- I used a dictionary because it makes it easy to search through it while
Then I used
Object.keys()
to get an array of the dictionarie's keys andmap
-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.
- I made some variables for
sum
,counter
to count the occurrence of each name,average
andavgArr
to store the averages - 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 theaverage
for each person. Then add thisaverage
to theavgArr
array. - I added
checked
property to each object to avoid taking the same object more than one time if it'strue
skip that object, if the object doesn't have this property take this object, add thechecked
property and set it totrue
. 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]