JavaScript - USe .map(), .reduce(), and filter()

JavaScript - USe .map(), .reduce(), and filter()

.map()

Let me explain how it works with a simple example. Say you have received an array containing multipe objects each one representing a person. The thing you really need in the end, though, is an array containing only the id of each person.

// What you have

const students = [
   {id: 20, name: 'Iron man'},
   {id: 21, name: 'captain america'},
   {id: 22 name: 'hulk'},
   {id: 24, name: 'thor'},
   {id: 25, name: 'Clint Barton'}
];

// What you need
[20, 21, 22, 23, 24, 25]

There are multiple ways to achieve this. You might want to di it by creating an empty array, then using .forEach(), .for(...of), or a simple .for() to meet your goal.

Let's compare! Using .forEach():

studentsIds = [];
students.forEach(funtion(student) => {
   studentsIds.puch(student.id)
});

Notice how you have to create an empty array beforehand? Let's see what it look like when using .map():

cont studentsIds = students.map(function(student) =>{student} {
   reutrn student.id
});

We can even be more concise with arrow functions (requires ES6 support, Babel or TypeScript)

const studentsIds = students.map(student => student.id)

So how does .map() work? Basically is takes 2 argument, a callback and an optional context (will be considered as this in the callback) which I did not use in the previous example. The callback runs for each value in the array and returns each new value in the resulting array.

Keep in minf that the resulting array will always be the same length as the original array.

.reduce()

Just like .map, .reduce() also runs a callback for rach element of an array. What's different here is tha treduce passes the result of this callback (the accumulator) from one array element to the other.

The accumulator can be pretty much anything (integer, string, Object, etc.) and must be instantiated or passed when calling .reduce().

Time for an example! Say you have an array with these pilots and their respective years of experience:

const pilots = [
  {
    id: 10, 
    name: "Iron man",
    year: 14
  },
  {
    id: 2,
    name: 'Thor',
    year: 30
  },
  {
     id: 3,
     name: "captian America",
     year: 16 
   },
  {
     id:  4,
     name: "Hulk "
     year: 22
  }

];

We need to know the total years of expreience of all of them. Whit .reduce(), it's pretty straighforward:

var totalYears = pilots.reduce(function(accumulator, pilot) {
  return accumulator + pilot.years
}, 0);

Notice tha tI've set the staring value as 0. Icould have also used an existing cariable if necessary. After running the callback for each element of the array, reduce will return the finale value of our accumulator (in pur case: 82).

Let's see how this can be shortened with ES6's arrow funtions:

const totalYears = pilots.reduce((acc, pilot) => {
  acc + pilot.years, 0
})

Now let's say I want to find which pilot is the most experienced one. For that, Ican use reduce as well:

const mostecpPilot =  pilots.reduce(function(oldest, pilot){
  return (oldest.years || o) > pilot.years ? oldest : pilot;
}, {});

I name my accumulator oldest. My callback compares the accumulator to each pilot. If a pilot has more year of experience than oldest, then that pilot becomes the new oldest so that's the one I return.

As you can see, using .reduce() is an easy way to generate a single value or object from an array.

.filter()

What id you have an array, but only want some of the elements in it? That's where .filter() comes in!

Here's our data:

const pilots = [
  {
    id: 10, 
    name: "Iron man",
    year: 14
  },
  {
    id: 2,
    name: 'Thor',
    year: 30
  },
  {
     id: 3,
     name: "captian America",
     year: 16 
   },
  {
     id:  4,
     name: "Hulk "
     year: 22
  }

];

Say we want teo array now: one for hulk pilots, the other one for capAmerica, With .filter() it couldn't be easier!

const hulk = pilots.filter(function(pilot){
  return pilot.name === "hulk"
});

const capAmerica = pilots.filter(function(pilot){
  return pilot.name === "captian America"
});

That's it! And it even shorter with arrow fucntion:

const  hulk = pilots.filter(pilot => {
  pilot.name === "hulk"
});
const  capAmerica = pilots.filter(pilot => {
  pilot.name === "captian America"
})

basically if the callback function returns true, the current element will be in the resulting array. If it returns false, it won't be.

Tyr it!

Try to replace some of your for loops with .map(), .reduce(), .filter() where it seems to fit. I gurarantee your code will be way less clunky and much easier to read.