They will help to find() your inner soul, filter() out your feelings, make a road map() of your life and surely reduce() your pains.
For quick read. Checkout this amazing album!
After your native language which you use for daily communication and sharing your emotions one should definitely have command over JavaScript (for coders obviously). Talking about command, the area which we require some exploration is JavaScript array methods. Now most of the ninja coders out there are already familiar with array methods, but this one is for those Pokemon trainers who have just started their journey in JS. Without further ado lets take a one on one with JavaScript array methods.
Not all arrays are meant to loop, some are there to love.
We have an employee data set array over which we will use the array methods. A single employee object consist of following properties:
{
"code": "CT7207",
"salary": 40000,
"id": 1007,
"job": "Manager",
"department": "Operations",
"name": "Bently Smith",
"hobbies": ["Sports", "Reading", "Painting"]
}
The link for git repository is posted at the end of this post. Now let start building up queries for employee array to understand the array methods.
To handle different kind of queries we are using different array methods. Some queries have alternative solutions too which are further explained.
employees.find(i => i.id === 1003);
The find() method is used to fetch a single item from an array when the specified condition met; it will return undefined otherwise. In the above query it will return the employee who is having id 1003.
employees.findIndex(i => i.id === 1008);
The findIndex() method is used to find the index of an item from an array when the specified condition met; it will return -1 otherwise. In the above query it will return the employee who is having id 1003.
employees.filter(i => i.job === 'Salesman');
The filter() method is used to filter array items based on the specified condition; it will return a new array having items which based on the specified condition or it will return an empty array otherwise. In the above query it will return the employees those are having job as 'Salesman'. The filter() method is similar to SQL selections which is performed using WHERE clause.
employees.filter(i => i.salary > 40000);
employees.filter(i => i.salary > 50000 && i.department === 'Research');
employees.map(i => ({ name: i.name, salary: i.salary }));
The map() method is use to manipulate array items based on the condition; it will return a new array having manipulated items; unlike filter() method it is not meant to limit the number of items instead it help to modify data as per your need. In the above query it will return an object array with items having only name and salary properties. The map() method is similar to SQL projections.
employees.map(i => ({ name: i.name, job: i.job, annual: i.salary * 12 }));
In the above query the map() method is providing annual salary by performing operation on the actual salary; this way we can manipulate data as per our need.
employees.map(i => {
const names = i.name.split(' ');
return { firstName: names[0], lastName: names[1] };
});
employees
.filter(i => i.salary > 10000 && i.salary < 20000)
.map(i => ({ name: i.name, salary: i.salary }))
.sort((emp1, emp2) => {
const name1 = emp1.name.toLowerCase();
const name2 = emp2.name.toLowerCase();
if (name1 < name2) {
return -1;
} else if (name1 > name2)
return 1;
else return 0;
});
In the above query we are having a chain of array methods each of which doing their own task and return a resultant array which is then given as an input to subsequent methods. Here the sequence of methods in which they are appearing matters from a logical perspect. As the filter() methods appears first it limits the number of rows followed by map() method which will act on the reduced resultant array followed by sort() method which will perform the sorting on the array having objects with name and salary properties.
employees.filter(i => i.salary > 10000).length === employees.length;
The above filter() method will work like a charm and the further length check will provide us the solution to our query. But instead of filter() method which primary focus is to create a new array based on the condition we have a very performant alternative; the every() method.
employees.every(i => i.salary > 10000);
The every() method returns true if all items in an array satisfies the given condition and false otherwise. The filter() method as a solution is slightly slower as compared to every() method as the primary task of filter() method is to create a filtered array which consumes some computation time as compare to every() method. Also the syntax is more clear with every() method.
employees.some(i => i.salary > 60000);
The some() method returns true if any item in an array satisfies the given condition and false otherwise.
employees.filter(i => i.hobbies.filter(hobby => hobby === 'Reading').length);
For such complex scenarios where the object inside arrays have their own arrays and so on, some() and every() methods provide a clear and an easy approach as compare to filter() method. So this solution can be easily achieved using some() method as below.
employees.filter(i => i.hobbies.some(hobby => hobby === 'Reading'));
employees.map(i => i.salary).reduce((accumulator, currentValue) => currentValue + accumulator, 0);
The reduce() method iterate on each element of an array and returns a single computed output value. It takes accumulator and currentValue, where the accumulator is the resultant value from previous iteration and currentValue points to current iterated element. Optionally, we can provide the initial value to start with, which is supplied to the accumulator for the very first iteration. In the above solution the mapped salary are calculated and the sum is obtained using reduce() method.
employees.map(i => i.salary).reduce((accumulator, currentValue) => currentValue + accumulator) / employees.length;
There is no such array method right now which solves the above query directly. So one option left is forEach() method. In the below solution we can get the maximum salary in the maxSalary variable.
let maxSalary = 0;
employees.forEach(item => {
if (item.salary > maxSalary) {
maxSalary = item.salary;
}
});
A shorter but slightly complex solution can be achieved using Math.max() method. It provides max out of supplied parameters. So the Math.max(58, 85, 10) is 85. Now in our case instead of indivdual comma sperated values we have array of salaries. Here the spread syntax (...) comes to the rescue. The spread syntax breaks down an array into comma seperated arguments in order to supply it to a function. Checkout below solution using Math.max() and spread syntax.
Math.max(...employees.map(i => i.salary));
The spread syntax was added to JavaScript in ES6(ES2015). So to acheive above solution without spread syntax we have apply() method. Checkout below solution using Math.max() and apply() method.
Math.max.apply(0, employees.map(i => i.salary));
Math.min(...employees.map(i => i.salary));
Now here comes the trouble. Our employees array hold up jobs for all employees some of them have the same job as others. In order to collect the distinct values out of an array is troublesome and leave the only option to iterate entire array and apply some logic to find the distinct values. Fortunately, we have an alternate which is a combination different methods and data structure. Have a look on the provided solution.
Array.from(new Set(employees.map(i => i.job)));
The Set() object lets you to store unique values. So we are taking advantage of Set object and provding array of jobs to the Set object which will give us a Set object of distinct jobs. Now Set objects are not a normal object nor an array instead they similar to Sets which we had in our Maths.
In order to obtain an array of distinct jobs the last thing to do is to pass this Set object to from() method of Array class. The from() method will convert any given array-like iteratable object to an array.
Life is not that easy as it looks like. We come to know how to get distinct values from an array. But how to get distinct values from an array where the values are itself an array?
Will go step wise to take down this one. We have to fetch hobbies so for that will use map() method which will give us an array of hobbies of the array. What we need to do is combine all these arrays of arrays to a single array which holds all the values of sub array.
So here comes a hero named flat() method. It will flatten all such child arrays to one single array of all the values. Now, finally from all these values combined we can do what we was doing previously and get the distinct hobbies.
Array.from(new Set(employees.map(i => i.hobbies).flat()));
There is one more super hero, which even reduce your mapping and flatting, 2 different efforts into one. Meet flatMap() method which does the mapping followed by flatting the values.
Array.from(new Set(employees.flatMap(i => i.hobbies)));
In order to club array values as single string seperated by a seprator we can go with join() method. Following solution help us to construct the string as 'Likes Reading/Sports'.
employees.map(i => ({ name: i.name, likes: 'Likes ' + i.hobbies.join('/') }));
In order to remove any element from an array we use splice(). The splice() method can remove any number of elements starting from proivded index. In the above query we just have to remove employee who have id as 1010. Following solution will do so.
const employeeIndex = employees.findIndex(i => i.id === 1010);
employees.splice(employeeIndex, 1);
Caution some complex shit ahead. Let's break this out in pieces. First, we have to find how many departments, we have and that too distinct so to further fetch salary total. Second, will compute the sum of salaries by iterating the distinct department obtained through the first step.
Fetch distinct departments
Array.from(new Set(employees.map(i => i.department)));
Fetch sum of salary for only one department
employees
.filter(i => i.department === 'Sales')
.map(i => i.salary)
.reduce((accumulator, currentValue) => currentValue + accumulator)
Finally will club these 2
Array
.from(new Set(employees.map(i => i.department)))
.map(department => ({
department,
salary: employees
.filter(i => i.department === department)
.map(i => i.salary)
.reduce((accumulator, currentValue) => currentValue + accumulator)
}));
The outer map() method will create an object having department name and salary, and salary for each department is calculated using the second solution mentioned previously.
This will be taken care by the string method named startsWith() which returns true if given string starts with a given character/collection of characters and false otherwise.
employees.filter(i => i.name.toLowerCase().startsWith('e'));
Calling toLowerCase() method first is to make the cases identical.
Just like startsWith() we have endsWith() does the same thing but for the last part of string.
employees.filter(i => i.name.toLowerCase().endsWith('n'));
The search() method will search the part of string appears anywhere in the specified string returns true if found and false otherwise.
employees.filter(i => i.name.toLowerCase().search('tly') !== -1);
December 31, 2020
October 19, 2020
March 02, 2022