DEV Community

Riko
Riko

Posted on

A beginner's guide to the Array .map and .reduce methods

Introduction

JavaScript's Array iterator methods .map and .reduce were some of the more confusing things to learn as a new JavaScript programmer. In this blog I walk through each method and explain how to use them. As a beginner myself, I hope to demonstrate my own learning and help other beginners who may also struggle to understand these methods.

I'll use an array of students where each student object has keys studentId, name, age, score, and classes (an array of Class IDs the student is enrolled in).

const students = [
  { id: "A001", name: "Alice", age: 22, gpa: 4.0, classes: ["C101", "C102", "C103"] },
  { id: "B002", name: "Bob", age: 24, gpa: 3.5, classes: ["C101", "C104"] },
  { id: "C003", name: "Charlie", age: 23, gpa: 3.6, classes: ["C102", "C105"] },
  { id: "D004", name: "David", age: 25, gpa: 2.9, classes: ["C103", "C106"] },
  { id: "E005", name: "Eve", age: 21, gpa: 3.0, classes: ["C104", "C105", "C106"] }
];
Enter fullscreen mode Exit fullscreen mode

.map()

  • Description: iterates over an array and applies a callback function to each element, modifying them in some way
  • Arguments: a callback function
  • Returns: a new array with the elements that have been modified by the callback function

Use .map to create a new array using an object key

.map makes it super quick to get a list of particular values from an array of objects using a key. For example, we can use .map to get a list of studentIds

const studentIds = students.map(student => student.id)
//[ 'A001', 'B002', 'C003', 'D004', 'E005' ]
Enter fullscreen mode Exit fullscreen mode

This uses a function expression with an implicit return. This is basically saying, for each student, get their ID, and return the ID to the new studentIds array.

Use .map to create a new array of objects with additional data

We can also use map to get create a new list of students with their IDs and the count of classes they are enrolled in, based on the length of the nested classes array.

const studentClassCount = students.map(student => {
    return {
        id: student.id,
        countOfClasses: student.classes.length
    }
})
/*
LOG: [
{ id: 'A001', countOfClasses: 3 },
{ id: 'B002', countOfClasses: 2 },
{ id: 'C003', countOfClasses: 2 },
{ id: 'D004', countOfClasses: 2 },
{ id: 'E005', countOfClasses: 3 }
]
*/
Enter fullscreen mode Exit fullscreen mode

Because this use of .map is constructing new objects, the anonymous function that's passed to .map has to explicitly return each object with the student id and the new countOfClasses key that gets the length of each student's nested classes array.

.reduce()

  • Description: iterates over an array and applies a function to each element and calculates a single value
  • Arguments: a callback function (which can have 3 arguments) and an initial value to start
  • Returns: A single value (such as a string, integer, boolean, or another object/array)

Reduce is helpful for calculating a single value from an array, such as a string, integer, boolean, or another object/array. But its argument structure can be difficult to understand. Let's break it down:

  1. The first argument is a callback function, and this function itself can have three arguments:
  • An accumulator (sometimes abbreviated as accum or acc), which is the value that will be added to (or accumulated) with each iteration over the array, and it will be passed into the next iteration. This accumulator will be the thing that is returned by reduce once the entire array has been iterated over with the callback function.

  • A current value (sometimes written as value), which will represent each array element as it is passed to the callback function

  • An index, an optional argument that indicates which index in the array for the function to start at. If this is not provided, the callback function will start with index 0 by default (the first element in the array).

  1. An initial value to start with, such as 0 if you're calculating a numeric value, or an object/array. Objects can be empty, but you can include new keys if needed.

To demonstrate .reduce and these arguments, let's use a simple array of numbers and sum them together.

const numbers = [1, 2, 3];
const sum = numbers.reduce((acc, value, index) => {
    console.log(`Index: ${index}, Accumulator: ${acc}, Value: ${value}`);
    return acc + value;
}, 0);

/* LOG:
Index: 0, Accumulator: 0, Value: 1
Index: 1, Accumulator: 1, Value: 2
Index: 2, Accumulator: 3, Value: 3
*/

console.log(sum)
//LOG: 6
Enter fullscreen mode Exit fullscreen mode
  1. We call reduce on the numbers array, and pass an arrow callback function that has 3 arguments: acc, value, `index
  2. The callback function does 2 things for each iteration: it first console logs each of the arguments, and it returns the sum of acc and value
  3. After the callback function, note that 0 is provided as the second argument to .reduce. This is the initial value of acc that the sum will start with.
  4. In the first iteration, the index starts at 0, the acc is 0 (the initial value provided as second argument to .reduce), and the current value is the first element in the array: 1
  5. The callback function returns acc + value, or 0 + 1 which equals 1.
  6. 1 is then passed into the second iteration as the acc. The index is now 1, accumulator is 1, and the next array value in the array is now 2
  7. This repeats for each element in the array.
  8. sum ultimately returns 6 as the sum of 1 + 2 + 3

Now let's return to our students example and see what we can do with .reduce.

Use reduce to calculate a single value

If we wanted to calculate an average GPA for our set of students, we can use .reduce to get the total GPA which can then be used to calculate an average.

`javascript
const totalGPA = students.reduce((accumulator, student) => {
return accumulator + student.gpa;
}, 0);
const averageGPA = totalGPA / students.length;

//LOG: Total GPA: 17
//LOG: Average GPA: 3.4
`

Use reduce to create a new object

We want to categorize our students based on their GPA scores. To do this, we'll want to loop through each student's GPA and determine where each GPA falls in our categories.

`javascript
const gpaCategories = students.reduce((accumulator, student) => {
let category;
if (student.gpa === 4.0) {
category = "4.0";
} else if (student.gpa >= 3.5) {
category = "3.5-3.9";
} else if (student.gpa >= 3.0) {
category = "3.0-3.4";
} else {
category = "below 3.0";
}

if (!accumulator[category]) {
accumulator[category] = [];
}

accumulator[category].push(student.name);
return accumulator;
}, {});
`

The callback function uses if/else statements to determine the category in which each GPA falls. The second if statement creates the category keys in the accumulator object after checking whether the category key already exists.

Then each student name is pushed into the category key according to their GPA.

This will return a new object:

javascript
{
'4.0': [ 'Alice' ],
'3.5-3.9': [ 'Bob', 'Charlie' ],
'below 3.0': [ 'David' ],
'3.0-3.4': [ 'Eve' ]
}

Conclusion

In this blog I demonstrated how .map and .reduce can be used, providing a break down of each method's arguments and inner workings. .map is a powerful and concise method for creating new arrays of modified elements, while .reduce can derive a single calculated value or object/array.

Happy learning!

Top comments (0)