
Overview
Previously, we came to understand some basics aboutmap,filter, and the 'King 👑' Array Method -reduce.
This post will just serve as some slightly more practical application where we'll apply our knowledge to an array of student data.
To follow along, you can fork this:
The code shown 👆🏽 is simply to get you an Array of 50 random numbers between 50 and 100. We will use these as a basis to retend that these are some exam scores for a class 🤷🏽♂️.
Transforming our Data into Objects
It doesn't make sense to just have some random numbers. These should be objects with some student ids associated with them.
We'll retend that our ids are just from 1 to 50. So, our data will be transformed to something like:[{id: 1, score: 55} all the way down.
Transforming each and every piece of data sounds like...🤔...map❗
const studentScores = examResults.map((examResult, index) => ({studentId: index + 1, examResult}))
Breakdown
(examResult, index) shows usage of an optional 2nd parameter,index that we can specify in themapcallback function. Thisparameter represents theindex of the current item. With 50 elements, this will start at0 and end at49.
({studentId: index + 1, examResult}) We are returning anobject literal with 2 🔑s,studentId andexamResult.
studentId's value is nothing but the currentindex + 1 - so it will run from 1-50, as we see in the results.
examResult is nothing but...theexamResult 🤷🏽♂️. We useobject shorthand so that the 🔑 takes on that name and thevalue is thevalue bound toexamResult (which is that firstparameter in the _callback function).
Our results look something like this:
[{ studentId: 1, examResult: 75},{ studentId: 2, examResult: 85},{ studentId: 3, examResult: 61},Add Letter Grades
Next, we want to add another 🔑,letterGrade. This will give us the letter grade on a standard 10 point scale.
For this, let's make apure library function that we can reuse at will:
constassignLetterGrade=score=>{if(score>90){return"A"}if(score>80){return"B"}if(score>70){return"C"}if(score>60){return"D"}return"F"}This function simply takes in ascore andreturns the appropriate 'letter grade.' Note 🎵 that there is no need forelse with the use of 'early'returns inside of theifs.
conststudentGrades=studentScores.map(studentScore=>{// Avoid mutation of the original object dataconstcurrStudentScore={...studentScore}currStudentScore.letterGrade=assignLetterGrade(currStudentScore.examResult)returncurrStudentScore})We saw this same sort of technique in our previous post
currStudentScore.letterGrade = assignLetterGrade(currStudentScore.examResult)
Here, we are doing the update; that is, adding a new 🔑 and using thereturned result fromassignLetterGrade that we wrote earlier.
Filter Out Low Scores
Again, let's write apure library function that just takes in anynumber and some specific 'threshold' number and justreturns aboolean that let's us know whether it's 'low' or not, based on the 'threshold:'const isLow = (num, threshold) => num < threshold
Now, we'll usefilter along with this 'library function' to create a list of all of the students that scored under75:const lowGrades = studentGrades.filter(({examResult}) => isLow(examResult, 75))
Inside of ourfiltercallback, we aredestructuring the property that we care about,examResult.
We send this to our 'library function' to see if the score is less than75. If it is, this entire 'student object' will bereturned. The result if anarray of all students that have scored less than75.
[{ studentId: 1, examResult: 57, letterGrade:'F'},{ studentId: 2, examResult: 71, letterGrade:'C'},{ studentId: 3, examResult: 74, letterGrade:'C'},Get Average Score
To figure out the average score, we will need to get the total after adding up each and everyexamResult, and then divide the thelength ofstudentGrades, which is of course '50.'
studentGrades.reduce((total,{examResult})=>{total+=examResult;returntotal},0)/studentGrades.lengthBreakdown
(total, {examResult} -reduce requires twoparameters. One keeps the '🏃🏽♂️ total' (commonly referred to as an 'accumulator). The secondparameter is each individual 'student grade record,' from which we aredestructuring just theexamResult.
total+=examResult;returntotalHere we are updatingtotal and continuing toreturn it as we keepinterating over each 'student score.'
Stepping back and taking a look 👀 atreduce, we can see that there are 2arguments. The first is thecallback function (that takes 2 parameters as discussed 👆🏽) _and the second is the0.
reduce((total,{examResult})=>{total+=examResult;returntotal},// Optional second parameter initializes 'total' to '0'0)}, 0 -⚠️ This part is critical. Thisparameter initializestotal to be0. W/o this,total would be initialized as thefirst element in the 'student grades array' - an object. So, we would be 'adding' an _object literal and we would getNaN 👎🏽.
/ studentGrades.length Finally, we are dividing our numerical total by that length, '50,' resulting in the average! 👏🏽
Tally Up the Grade Distribution
For our final task, we want to know how many "As," "Bs," "Cs," etc. there were. We want our results to look something like this:{A: 10, B: 12 - anobject literal where each 🔑 is one of the letter grades and thevalue is the 'count' of however many of that grade that there is...
constgradeTally=studentGrades.reduce((tally,{letterGrade})=>{// Does 'tally' already have a 🔑 for the current letter grade?if(tally[letterGrade]){// Add 1 to its valuetally[letterGrade]=tally[letterGrade]+1}else{// Initialize it with a value of 1tally[letterGrade]=1}returntally},// Initialize 'tally' as an empty object{})Breakdown
tallyis initialized as an empty object -{})- We bring in the first
letterGrade-{letterGrade} - Usebracket notation to see if there is any currentvalue inside of
tallyfor the current letter grade:tally[letterGrade]. Naturally, astallyis empty the first time, this will always befalse. - Set this 'letter grade 🔑' inside of
tallywith avalue of1-tally[letterGrade] = 1 - Continue this process by either adding a new 🔑 with a value of
1,or byadding 1 to the current value.
Refactor ♻️ With a Ternary
constgradeTally=studentGrades.reduce((tally,{letterGrade})=>{tally[letterGrade]=tally[letterGrade]?tally[letterGrade]+=1:1returntally},{})Final Code
Top comments(0)
For further actions, you may consider blocking this person and/orreporting abuse




