Map-Reduce-Filter-Find In Javascript ES6

If you are a fan of javascript and use it daily then you will love this 😃

Javascript is a language that give freedom of writing code in any style, from imperative to declarative styles. Most programmer use imperative because either they are coming from OOPs background, may be they love it or they are not familiar with other style. Before we dive into the declarative style which is FP, let’s understand the differences in two by looking at an example(If you already know the difference then you may skip few paragraphs).


Imperative


// to calculate the sum of array elements
const sum = (arr) => {
  let result = 0; 
  for (let i = 0; i < arr.length; i++) {
    result += arr[i];
  }  
  return result;
};

Imperative style is cool but imagine what if there is a complex mathematics logic here then size of code and the readability will suck. It increases the cognitive load when reading, and over time makes it easier to faulter in reasoning and logic. Also, the main complexity of this code snippet derives from the fact that instead of telling the computer what we want it to do, we are instructing it on how to do it.

Declarative


// calculate the sum of array elements
const sum = (arr) => arr.reduce((total, item) => total += item, 0);

Now, this looks pretty clean, shorter, expressive, concise code, less error prone, easier to maintain and easier to debug. We are telling computer what we want it to do rather how to do it.

Declarative approach are easily optimisable at complier end and also have less side effects.

Note: if you are concerned about the performance of above two and other javascript function (map, reduce, filter, find) then you should read here for small data set and can view here for large data set(100–1000000)


Without more delay, let’s start the real action with most used Javascript function for functional programming.

Map


// definition 
collection.map((currentValue, index) => {
    // Return element for newArray
});
// example
const arr = [1,2,3,4,5];
const newArray = arr.map(i => i*10);
// return a new array with all value as multiple of 10;


Map works on an array and return an array that’s it. Above code snippet works on an collection i.e an array and takes a callback with current iteration value, index as arguments and return a new array.

Note: Maps are well suited for change/transforming whole array rather than breaking the flow for some conditions, Map suck’s performance wise, check out here but are easy to be used for small data sets.

Reduce


// definition 
collection.reduce((accumulator, item, index) => {
    // logic to perform to get accumulator as a return value
}, initialValue for accumulator);
// example
const arr = [1,2,3,4,5];
const total = arr.reduce((acc, item) => acc+= item, 0);
// return a total as 15

Reduce works on an array but can return anything you want it to return. As the name speaks for itself it can be reduce to anything and can behave like map, find, filter or any other javascript function. The above code snippet works on an array and reduce to compute the total value of item of array.

Explanation of example above : On reduce first run, acc is assigned a 0 value and then acc+= item i.e acc = acc+item which will compute to0+1 i.e 1. This 1 will be acc value for next iteration and this continues until we are done with all array items.

Find


// definition 
collection.find((item) => {
    // return first element that satisfy the condition
});
// example
const arr = [1,2,8,4,5];
const value = arr.find(i => i%4 == 0);
// return the first value i.e 8 

Find works on an array and return the first element that satisfy the condition in function.

Note: Easy, simple but not efficient on large data set, why ? look here

Filter


// definition 
collection.filter((currentValue, index) => {
    // logic to filter array on
});
// example
const arr = [1,2,3,4,5];
const newArray = arr.filter(i => i%2 == 0);
// return a new array with value [2, 4]

Filter works on array return an array for filtered items.


Lets use them for some real world scenarios + some ES6. (lets try some ARMD on below object keys)

Wondering what is ARMD its Add, Read, Modify, Delete, its cool to coin your own jargon 😄

const users = [
  {
    id: 1,
    name: "Jonathon Haley",
    username: "Monte.Weber2",
    email: "[email protected]",
    phone: "1-563-675-1857 x11708",
    website: "carmela.net",
    password: "hashed_password"
  },
  {
    id: 2,
    name: "Dean John",
    username: "dd.1",
    email: "[email protected]",
    phone: "1-123-543-1857 123212",
    website: "dd.net",
    password: "Dean_hashed_password"
  }

We will use users as array for further examples

1. ARMD — Adding a new element to users

const newUser = {
    id: 4,
    name: "Denomer Crazy",
    username: "crazy.1",
    email: "[email protected]",
    phone: "",
    website: "crazy.app",
    password: "crazed_checker"
};
const newData = [...users, newUser]; // add element at last
or 
const newData = [newUser, ...users]; // add element at first
or 
const newData = users.concat(newUser) // the old way

The use of es6 spread operator make super easy to add elements to array. We can use spread operator to concat two different array, modify shape of objects or add dynamic key value pairs etc.

const hobbies = ['chess', 'pool'];
const newUsers = users.map(u => ({...u, hobbies}))
// this will add hobbies to users array and return newUsers array

2. ARMD — Get email address, phone number and website of users into new array

const contactInfo = users.map(({email, website, phone}) => ({email, website, phone}));

The use es6 of destructuring of object keys and map to get the contact info array for user.

3. ARMD — Find and replace value for key of objects

const newUsers = users.map(u => u.id == 2? ({...u, name: 'te'}): u);
// this will return newUsers with all user having name 'te'


4. ARMD —Delete some key’s from object

Note: We will actually not delete the key but return a new object, if you want to delete the key use delete operator, here we are considering object immutability.

To delete keys there are lot of ways but we will look at the most easy, single lined. Lets try to delete website from users.

const newUsers = users.map({id, email, name, username, phone, password} => ({id, email, username, email, phone, password}));
// will return an array with all keys other than website

Above code seems to be practically difficult to code for big objects.

const newUsers = users.map(u => Object.keys(u).reduce((newObj, key) => key != 'website' ? { ...newObj, [key]: u[key]} : newObj, {}));


We map through the users and then on each user we do a reduce and form a new object (newObj) and then check for website key, if its a website we return the previously formed newObj, if not then we do a spread operator and add require key to obj and finally return newObj.


If anything is not clear or you want to point out something, please comment down below.

You may also like my other articles

Proxy In Javascript - 2019

Js ES6 Iterables and Iterators - 2019

Javascript - Generator-Yield/Next & Async-Await - 2019

This keyword In Javascript 2019 - Javascript Context

Javascript- Currying VS Partial Application 2019

Javascript Performance Test 2019 [Part-1] - for vs for each vs (map, reduce, filter, find)

Structure Node.js App - Fractal Pattern - 2019



Email

About Deepak Gupta

Deepak is profound programmer and financial educator in India. He has co-founded couple of startup from scratch and worked in more than 12 startup and big corporate with different roles.

Owing to his interest, he has been writing blogs regarding JavaScript and other framework to help people starting with it. Also, love to educate people about trading and cryptoworld in his free time.

Subscribe to our email list

More Tags Of Your Interest