Mastering JavaScript Array Methods: map, filter and reduce

As I prepare for frontend interviews, I've been diving deep into some of the most essential JavaScript array methods: map, filter, and reduce. These methods are invaluable for data manipulation and often come up in technical interviews.

In this blog, I'll cover the basics of these methods, show how to create custom polyfills, and present some common interview questions.

Introduction to map, filter, and reduce

JavaScript's array methods map, filter, and reduce are powerful tools for transforming, filtering, and aggregating data. Let's start by understanding what each of these methods does.

map()

The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.

💡
It doesn’t modify the original array but returns a new array

Example:

const nums = [1, 2, 3, 4];

const multiplyThree = nums.map((num) => num * 3);
console.log(multiplyThree); // Output: [3, 6, 9, 12]

filter()

The filter() method creates a new array with all elements that pass the test implemented by the provided function.

💡
It returns a filtered array based on the condition specified in the callback function

Example:

const nums1 = [1, 2, 3, 4];

const moreThanTwo = nums1.filter((num) => num > 2);
console.log(moreThanTwo); // Output: [3, 4]

reduce()

The reduce() method executes a reducer function on each element of the array, resulting in a single output value. It’s often used for aggregating data.

💡
It reduces the array of values into a single value and returns it

Example:

const nums2 = [1, 2, 3, 4];

const sum = nums2.reduce((acc, curr) => acc + curr, 0);
console.log(sum); // Output: 10

Polyfills

To fully grasp these methods, it's helpful to understand how they work under the hood. Creating polyfills (custom implementations) is a great way to do this.

💡
It's an important Interview question

Map Polyfill

Example:

Array.prototype.myMap = function (cb) {
  let temp = [];
  for (let i = 0; i < this.length; i++) {
    temp.push(cb(this[i], i, this));
  }
  return temp;
};

Filter Polyfill

Example:

Array.prototype.myFilter = function (cb) {
  let temp = [];
  for (let i = 0; i < this.length; i++) {
    if (cb(this[i], i, this)) temp.push(this[i]);
  }
  return temp;
};

Reduce Polyfill

Example:

Array.prototype.myReduce = function (cb, initialValue) {
  let accumulator = initialValue;
  for (let i = 0; i < this.length; i++) {
    accumulator = accumulator !== undefined ? cb(accumulator, this[i], i, this) : this[i];
  }
  return accumulator;
};

Some Interview Questions

Now that we understand the basics and polyfills, let's tackle some common interview questions using these methods. We'll use an array of student records for these examples.

let students = [
  { name: "Akshay", rollNumber: 31, marks: 80 },
  { name: "Hrithik", rollNumber: 15, marks: 69 },
  { name: "Salman", rollNumber: 16, marks: 35 },
  { name: "Shahrukh", rollNumber: 7, marks: 55 },
];

// Q1 - Return only the names of students in capital letters

let names1 = [];
for (let index = 0; index < students.length; index++) {
  names1.push(students[index].name.toUpperCase());
}
console.log(names1); // Output: ["AKSHAY", "HRITHIK", "SALMAN", "SHAHRUKH"]

let names2 = [];
students.forEach(student => {
  names2.push(student.name.toUpperCase());
});
console.log(names2); // Output: ["AKSHAY", "HRITHIK", "SALMAN", "SHAHRUKH"]

let names3 = students.map(stu => stu.name.toUpperCase());
console.log(names3); // Output: ["AKSHAY", "HRITHIK", "SALMAN", "SHAHRUKH"]

// Q2 - Get the details of students who scored more than 60 marks.

let names4 = students.filter(stu => stu.marks > 60);
console.log(names4); // Output: [{ name: "Akshay", ... }, { name: "Hrithik", ... }]

// Q3 - Get the details of students who scored more than 60 marks and have rollNumber greater than 15.

let names5 = students.filter(stu => stu.marks > 60 && stu.rollNumber > 15);
console.log(names5); // Output: [{ name: "Akshay", ... }]

// Q4 - Sum total of the marks of the students

let totalMarks1 = students.reduce((acc, emp) => acc + emp.marks, 0);
console.log(totalMarks1); // Output: 239

// Q5 - Get only the names of the students who scored more than 60 marks

let names = students.filter(stu => stu.marks > 60).map(stu => stu.name);
console.log(names); // Output: ["Akshay", "Hrithik"]

// Q6 - Print the total marks of the students with marks greater than 60 after 20 marks have been added to those who scored less than 60.

let totalMarks = students
  .map(function (stu) {
    if (stu.marks < 60) {
      stu.marks += 20;
    }
    return stu;
  })
  .filter(stu => stu.marks > 60)
  .reduce((acc, curr) => acc + curr.marks, 0);

console.log(totalMarks); // Output: 255

Conclusion

Understanding and utilizing map, filter, and reduce in JavaScript is crucial for effective data manipulation. These methods not only simplify your code but also make it more readable and maintainable. By creating custom polyfills, you gain a deeper understanding of their inner workings, enhancing your JavaScript skills further. Whether you're transforming arrays, filtering data, or aggregating values, these array methods are indispensable tools in your programming arsenal.

As I continue to prepare for my frontend interviews, mastering these methods and being able to implement them effectively will undoubtedly be a significant advantage.

Happy coding!