Movatterモバイル変換


[0]ホーム

URL:


Skip to content
DEV Community
Log in Create account

DEV Community

Cover image for Applying Array Superpowers 🦸🏽‍♂️
Manav Misra
Manav Misra

Posted on

     

Applying Array Superpowers 🦸🏽‍♂️

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},
Enter fullscreen modeExit fullscreen mode

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"}
Enter fullscreen modeExit fullscreen mode

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})
Enter fullscreen modeExit fullscreen mode

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'},
Enter fullscreen modeExit fullscreen mode

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.length
Enter fullscreen modeExit fullscreen mode

Breakdown

(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;returntotal
Enter fullscreen modeExit fullscreen mode

Here 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)
Enter fullscreen modeExit fullscreen mode

}, 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{})
Enter fullscreen modeExit fullscreen mode

Breakdown

  1. tally is initialized as an empty object -{})
  2. We bring in the firstletterGrade -{letterGrade}
  3. Usebracket notation to see if there is any currentvalue inside oftally for the current letter grade:tally[letterGrade]. Naturally, astally is empty the first time, this will always befalse.
  4. Set this 'letter grade 🔑' inside oftally with avalue of1 -tally[letterGrade] = 1
  5. Continue this process by either adding a new 🔑 with a value of1,or byadding 1 to the current value.

Refactor ♻️ With a Ternary

constgradeTally=studentGrades.reduce((tally,{letterGrade})=>{tally[letterGrade]=tally[letterGrade]?tally[letterGrade]+=1:1returntally},{})
Enter fullscreen modeExit fullscreen mode

Final Code

Top comments(0)

Subscribe
pic
Create template

Templates let you quickly answer FAQs or store snippets for re-use.

Dismiss

Are you sure you want to hide this comment? It will become hidden in your post, but will still be visible via the comment'spermalink.

For further actions, you may consider blocking this person and/orreporting abuse

I'm a JS Subject Matter Expert (SME) that has spent the past few years spearheading curricula and teaching initiatives at colleges and bootcamps, in person and virtually.
  • Location
    62236
  • Education
    BS - Mech. Eng. - Missouri S&T
  • Joined

More fromManav Misra

DEV Community

We're a place where coders share, stay up-to-date and grow their careers.

Log in Create account

[8]ページ先頭

©2009-2025 Movatter.jp