If you’re new to JavaScript you probably haven’t heard of.map(),.reduce(),.filter(). Or you’ve heard of it, you’ve seen it used but you haven’t used it in your actual project. In many domestic development projects are to consider the compatibility of IE8, in order to be compatible with many JavaScript good methods and skills are buried. But I’ve noticed that in recent years, many development projects have completely abandoned the evil of Internet Explorer. If you don’t need a Stone Age compatible Internet Explorer anymore, start getting familiar with these methods for dealing with arrays.
Note that the three methods described in this article can be used in many other languages, as these methods and usage concepts exist in many other languages.
.map()
Let me show you how to use this method with a simple example. Suppose you now have an array of objects – each object represents an employee’s information. Now the end result you want is to pull out unique ID values for all employees.
// Employee data
var employees = [
{ id: 20.name: 'Captain Piett' },
{ id: 24.name: 'General Veers' },
{ id: 56.name: 'Admiral Ozzel' },
{ id: 88.name: 'Commander Jerjerrod'}];// The result you want
[20.24.56.88]
Copy the code
And there’s actually a lot of array manipulation to do that. The traditional approach is to define an empty array and use.foreach (),.for(… Of), or the simplest.for() to assemble the ids into the array you define.
Let’s compare the traditional processing with.map().
Using a forEach () :
var employeeIds = [];
employees.forEach(function (employee) {
employeeIds.push(officer.id);
});
Copy the code
Note that in the traditional way, we must have a predefined empty array variable. But if it were.map(), it would be much simpler.
var employeeIds = employees.map(function (employee) {
return employee.id
});
Copy the code
We can even use arrow methods in a more concise way (but with ES6 support, Babel, or TypeScript).
const employeeIds = employees.map(employee= > employee.id);
Copy the code
So how does.map() actually work? This method takes two parameters, the first is the callback method and the second is the optional content (which will be called this in the callback method). Each value/object in the array is looped into the callback method, and the new value/object is returned to the result array.
Note that the length of the resulting array is always the same as the length of the array being loaned over.
.reduce()
Familiar with.map(),.reduce() loops through a callback method, with each element in the array calling back into the callback method. The difference is that the value returned by the callback method is passed to the next callback method, and so on (equivalent to an accumulator).
The cumulative value in.reduce() can be the value of any attribute, including INTEGER, String, object, and so on. The cumulative value is either instantiated or passed to the next callback method.
Let’s go to the code and make a simple example! Suppose you have an array of pilots with the seniority of each pilot.
var pilots = [
{
id: 10.name: "Poe Dameron".years: 14}, {id: 2.name: "Temmin 'Snap' Wexley".years: 30}, {id: 41.name: "Tallissan Lintra".years: 16}, {id: 99.name: "Ello Asty".years: 22,}];Copy the code
Now we need to know the total seniority of all pilots. Using.reduce() is easier than eating.
var totalYears = pilots.reduce(function (accumulator, pilot) {
return accumulator + pilot.years;
}, 0);
Copy the code
Notice that I passed 0 for the second argument here. The second argument is the initial value of a cumulative value. Of course you can pass in a variable or whatever value you want if the scene needs this initial value. After iterating through each element in the array, the reduce method returns the final cumulative value (82 in our case).
Acc and Accumulator in this example are accumulator variables
If we use the ES6 arrow notation, we can write it more elegantly and concisely. A line of work!
const totalYears = pilots.reduce((acc, pilot) = > acc + pilot.years, 0);
Copy the code
Now if we need to find out which one is the most experienced pilot. In this case we can also use.reduce().
var mostExpPilot = pilots.reduce(function (oldest, pilot) {
return (oldest.years || 0) > pilot.years ? oldest : pilot;
}, {});
Copy the code
Here I changed the accumulator variable to oldest representing the old driver in the aircraft division. At this time, the callback method in Reduce compares each pilot, and each time the value of the pilot enters this callback method, the oldest variable will be overwritten by the one with higher seniority. At the end of the cycle, the oldest is the oldest.
Through these examples, you can see how using.reduce() can easily and elegantly fetch a single final value or object in an array.
.filter()
If you’re in a situation where you need to filter a portion of the data in an array,.filter() is your best friend.
We used the pilot’s data and added the value of the airline:
var pilots = [
{
id: 2.name: "Wedge Antilles".faction: "Rebels"}, {id: 8.name: "Ciena Ree".faction: "Empire"}, {id: 40.name: "Iden Versio".faction: "Empire"}, {id: 66.name: "Thane Kyrell".faction: "Rebels",}];Copy the code
Now we want to screen Rebels and Empire pilots separately, using.filter() is a snap!
var rebels = pilots.filter(function (pilot) {
return pilot.faction === "Rebels";
});
var empire = pilots.filter(function (pilot) {
return pilot.faction === "Empire";
});
Copy the code
As simple as that, using the arrow method (ES6) is even more elegant:
const rebels = pilots.filter(pilot= > pilot.faction === "Rebels");
const empire = pilots.filter(pilot= > pilot.faction === "Empire");
Copy the code
The principle is simple, as long as your callback method returns true, the value or object will be in the new array. If false is returned it will be filtered out.
Use a combination of.map(),.reduce(),.filter()
Now, the three functions we just learned are all available for arrays, and.map() and.filter() all return arrays. Then we can use it in series. Don’t say much on the code to try!
Let’s try it out with a little more interesting data. Let’s say we now have an array of Star Wars characters. Each field is defined as follows:
Id
: Unique ID of a charactername
: Character namepilotingScore
: Flight capability indexshootingScore
: Shooting ability indexisForceUser
: Whether you have telekinetic control ability
Our objective: to obtain the index of total flight ability of pilots with airborne control ability. Let’s take it one step at a time!
- First we need to get a pilot with the ability to fly in the air.
var jediPersonnel = personnel.filter(function (person) {
return person.isForceUser;
});
/ / the result set: [{...}, {...}, {...}] (Luke, Ezra and Caleb)
Copy the code
- In this code we get three pilot objects, each with the ability to control the air. Use this object to get the flight capability index value for each pilot.
var jediScores = jediPersonnel.map(function (jedi) {
return jedi.pilotingScore + jedi.shootingScore;
});
// Result: [154, 110, 156]
Copy the code
- After obtaining the index value of each pilot’s flight capability, we can use the accumulator (
.reduce()
) obtained the total flight capability index.
var totalJediScore = jediScores.reduce(function (acc, score) {
return acc + score;
}, 0);
// Result: 420
Copy the code
Here separate implementation method can achieve our goal, but in fact we can series, can write more concise and elegant! Let’s do something better!
var totalJediScore = personnel
.filter(function (person) {
return person.isForceUser;
})
.map(function (jedi) {
return jedi.pilotingScore + jedi.shootingScore;
})
.reduce(function (acc, score) {
return acc + score;
}, 0);
Copy the code
Isn’t that elegant? This code is beautiful! ❤ ️
If we write ES6 with arrows, it’s even more elegant!
const totalJediScore = personnel
.filter(person= > person.isForceUser)
.map(jedi= > jedi.pilotingScore + jedi.shootingScore)
.reduce((acc, score) = > acc + score, 0);
Copy the code
A: wow! Could the code have been written so elegantly? ! Guess what?
In fact, we only need to use.reduce() to get our target result. The above example is for teaching example, so we use 3 functions we have learned.
Let’s take a look at how it works with.reduce(), and let’s refresh it!
const totalJediScore = personnel.reduce((acc, person) = > person.isForceUser ? acc + person.pilotingScore + person.shootingScore : acc, 0);
Copy the code
Can’t imagine? Getting a feature in one line is not a dream!
Why discard.foreach ()?
In fact, when I first wrote the front end, IT was a bit of a handout, and every array was just a handout for loop, solving all the array handling problems. But in the last few years I’ve started to get into front and back end development, API interfacing. As we see more and more data processing, if we continue to use the for loop for everything, the data processing code will become more and more bloated and complex. So I’m starting to get rid of.foreach (). Start being an elegant programmer!
Why is it more elegant and aesthetically pleasing to write code using.map(),.filter(),.reduce()? Let’s use a practical example to compare.
Suppose we now connect to an interface and return an array containing two fields name: the name of the person and title: the corresponding position.
var data = [
{
name: "Jan Dodonna".title: "General"}, {name: "Gial Ackbar".title: "Admiral",},]Copy the code
The product manager gives you the requirement that you only show the title of the person.
Of course there are some front ends that say “I’m just a little front end, I’ll take care of the back end”. However, this interface is actually a generic interface to get the data of these employees, and is used in multiple places. Do you think it would be a good idea to write an extra interface for each page because it needs to be displayed differently? As a good front-end engineer 🦁️, this small case you can be handled very gracefully. Also, on a good team, the back end is really about interface generality, and it’s not acceptable to give them a bloated interface for your convenience. So the front end is going to reorganize the data at this point.
Let’s say the product now requires you to display only employee titles and employee information in the employee list. At this point we will write a data assembly method to follow the presentation requirements to change the data format.
Because of this requirement, using.foreach () to reorganize the data is relatively cumbersome, and the code becomes bloated.
We ignore the method of assembling the data, just as if we had written a method of assembling the data as formatElement. If we use forEach, we first need to define an empty array to receive the results.
var results = [];
data.forEach(function (element) {
var formatted = formatElement(element);
results.push(formatted);
});
Copy the code
So we need two methods to achieve this data result, but why write so bloated? Because forEach does not return a value, it simply gives you a loop and pushes the value into a predefined variable. It can be done in one method, and the point is that it’s done in one line of code.
To use our new trick, using.map() is very simple and elegant.
var results = data.map(formatElement);
Copy the code
conclusion
Did you learn? Try replacing your traditional for loop with.map(),.reduce(),.filter(). I guarantee that your code will get cleaner and more readable.
If you enjoyed this post, be sure to check out my blog for the next one where we’ll learn how to use.some() and.find() in JavaScript.
Insist on being an elegant programmer, insist on coding every day!