DEV Community

Cover image for Functional programming in JS using(map, filter and reduce)
Prathamesh Mali
Prathamesh Mali

Posted on • Edited on

Functional programming in JS using(map, filter and reduce)

Ever since I started learning react I heard this buzzword Functional Programming. I have searched all over the internet and found some useful resources, watched countless youtube videos and finally got the hang of it, And probably you'll get it too till the end of this article.
First we will see how programming paradigm works, then we will cover functional programming and once we know the basics we will go over the implementation with JavaScript's Map, Reduce and Filter method.

Programming Paradigms

Basically there are various approaches to write you programs. If you've done a CS major you'd probably know these and if you didn't don't worry its a method to solve a problem. There are two main paradigms Imperative programming and Declarative programming.

1. Imperative Programming

Imperative programming works by changing the program state through assignment statements. The main focus in this approach is how we achieve the goal

Advantages:

  • Very easy to implement
  • Contains loops and variables

Disadvantages:

  • More buggy compared to Declarative
  • Hard to maintain
  • Less efficient for long term
  • Parallel programming not available

Examples:

OOPS is one of the most famous programming paradigm. OOPS short for (Object Oriented Programming) it comes under Imperative programming. In this paradigm everything is revolving around classes and objects.

  • Languages: Java,Python,C++,Ruby, Smalltalk

2. Declarative Programming

Declarative programming is a way of building programs that express the logic of computation without describing its control flow.

Advantages:

  • Short and Efficient Code
  • Implemented by the methods not yet known at the time of programming
  • Characterized by high level of abstraction that's why easier to represent complex logic
  • Maintenance is possible irrespective of application development.

Disadvantages:

  • Hard to understand for external Devs
  • Hard to take characteristics of individual applications into account during programming

Examples:

Functional programming The functional programming paradigms has its roots in mathematics and it is language independent. The central model for the abstraction is the function which are meant for some specific computation and not the data structure. Data are loosely coupled to functions.

  • Languages: JavaScript,Haskell,Scala,Erlang, Lisp

Functional Programming

Functional programming is the process of building software by composing pure functions, avoiding shared state, mutable data, and side-effects. In functional programming application state flows through pure functions. As compared with OOP where the state is shared with methods and objects.

Main concepts to learn in Functional Programming:

  • Pure functions: pure function is the function which takes the input and gives the same output every single time. It does not affect the state. Pure function has no side effects
  • Function Composition: it is the process of combining two or more functions which gives us a new function. Composing functions together is like snapping together a series of pipes for our data to flow through.
  • Avoiding shared states: shared state is any variable, object or memory space in a program. which can be passed down between multiple scopes. But in functional programming we should avoid this for avoiding mutation of states which changes the state.
  • Avoiding side effects: side effect is a function causing the state change which is observable outside the function call other than its return value. In simple words when our current function is modifying the state outside the current function.

Implementing of functional programming in JS with (Map, Reduce and Filter)

I will be covering most used functional array methods and JS which are Map, Reduce and Filter. These are the holy grail of functional programming in JavaScript. It is the best way iterate over arrays without changing them. Lets get started.

1. Map

It can be applied to an array. The map() method creates a new array populated with the results of calling a provided function on every element in the calling array.

Syntax:

Regular JS:



let newArr = arr.map(function (currentValue, index, currentArray) {
    //logic for new array
});


Enter fullscreen mode Exit fullscreen mode

Using ES6 arrow functions:

I would suggest using arrow function where possible its a great way of writing JS. Because its cleaner and more readable.



let newArr = arr.map((currentValue, index, currentArray) => {
    //logic for new array;
});


Enter fullscreen mode Exit fullscreen mode
  • function: This will be callback function which can be declared before can be added as we use it.
  • currentValue: Current value is similar to arr[i] when we iterate over array using for loops
  • index: Current index of the item
  • currentArray: the array we are iterating over. In this case its "arr"

  • newArr will return a new array with our applied modifications.

Where can I use it ?

We can use map while iterating over arrays, normally where you use for loop, we can use map method instead. We can extract the valuable info from the objects and return it in a form of an array. Simply it can be used on the array which has definite length. I loved using map and ditched "for loop" since I started learning it, its a good practice in writing clean code.

Example 1: Finding square of each number in array

Without using Map:
In regular JS fashion we would approach this problem something like this. Create an empty array. Iterate over the given array. Take the item from the current array and square it.Push the squared item in the empty array.Return the new array



let arr = [1, 2, 3, 4, 5];

let squaredArray = [];

for (let i = 0; i < arr.length; i++) {
    squaredArray.push(arr[i] ** 2);
}

// Output:
console.log(squaredArray); // [ 1, 4, 9, 16, 25 ]


Enter fullscreen mode Exit fullscreen mode

With Map:
Now we can see some map magic. While doing the same thing using map we don't have to explicitly declare a new array map method creates it under the hood. map method returns a copy of the array.



// Using map and arrow function it be applied something like this:
const newArr = arr.map((val) => val ** 2);
console.log(newArr); // [ 1, 4, 9, 16, 25 ]


Enter fullscreen mode Exit fullscreen mode

In the above example we are calling the map method on arr and passing in the callback function which will return an array of

So now you can see, how powerful it is. If you are seeing it for the first time it can be little confusing but trust me if you try to embrace the difficulty and start using it.

Example 2: Add the index of the current item into itself



// Input:
const arr = [0, 1, 2, 3, 4, 5];

// Output:
// [ 0, 2, 4, 6, 8 ]


Enter fullscreen mode Exit fullscreen mode

Without using Map:



let newArray = [];

for (let i = 0; i < arr.length; i++) {
    newArray.push(arr[i] + i);
}

console.log(newArray); // [ 0, 2, 4, 6, 8 ]


Enter fullscreen mode Exit fullscreen mode

In the following example we will make use of 3 parameters. val is the current value of item, index od current item, arr is the current array that we are iterating

With Map:



const newArray = arr.map((val, index, arr) => val + arr[index]);

console.log(newArray); // [ 0, 2, 4, 6, 8 ]


Enter fullscreen mode Exit fullscreen mode

Example 3: Extract full name and title of the employees from given object

Object that we will be working with:



let EmployeesObject = {
    Employees: [
        {
            userId: "rirani",
            jobTitleName: "Developer",
            firstName: "Romin",
            lastName: "Irani",
            employeeCode: "E1",
            region: "CA",
            phoneNumber: "408-1234567",
            emailAddress: "romin.k.irani@gmail.com",
        },
        {
            userId: "nirani",
            jobTitleName: "Database Admin",
            firstName: "Neil",
            lastName: "Irani",
            employeeCode: "E2",
            region: "CA",
            phoneNumber: "408-1111111",
            emailAddress: "neilrirani@gmail.com",
        },
        {
            userId: "thanks",
            jobTitleName: "Program Directory",
            firstName: "Tom",
            lastName: "Hanks",
            employeeCode: "E3",
            region: "CA",
            phoneNumber: "408-2222222",
            emailAddress: "tomhanks@gmail.com",
        },
    ],
};


Enter fullscreen mode Exit fullscreen mode


// Storing employee Array in separately for readability
const data = EmployeesObject.Employees;

// Extracting the required data and storing into new array
const curatedData = data.map(
    (employee) =>
        `Name: ${employee.firstName} ${employee.lastName}, Title: ${employee.jobTitleName}`
);

console.log(curatedData);

// Output:
[
    "Name: Romin Irani, Title: Developer",
    "Name: Neil Irani, Title: Database Admin",
    "Name: Tom Hanks, Title: Program Directory",
];


Enter fullscreen mode Exit fullscreen mode

2. Filter

Filter is a higher order function which will loops through an array, and for each item going to pass it in callback function. It will expect the callback function to return either true or false, to tell filter whether pr not this item should be in the new array. The filer() method also creates a new array but only with the elements which passes the test provided in the callback function.

Syntax:

Regular JS:



let newArr = arr.filter(function (currentValue, index, currentArray) {
    //Condition for new array
});


Enter fullscreen mode Exit fullscreen mode

Using ES6 arrow functions:



let newArr = arr.filter((currentValue, index, currentArray) => {
    // Condition for new array
});


Enter fullscreen mode Exit fullscreen mode
  • function: This will be callback function which checks the condition if its true or false for each item
  • currentValue: Current value is similar to arr[i] when we iterate over array using for loops
  • index: Current index of the item
  • currentArray: the array we are iterating over. In this case its "arr"

  • newArr will return a new array with our applied modifications.

Example 1: Find how many students pass the test

You are provided with the marks of students, passing marks is 35, you have to find how many students passed the test



let marks = [34, 56, 67, 12, 98, 71, 45, 32];


Enter fullscreen mode Exit fullscreen mode

Without using Filter:



let passed = 0;
for (let i = 0; i < marks.length; i++) {
    if (marks[i] > 35) {
        passed++;
    }
}

console.log(passed); // 5


Enter fullscreen mode Exit fullscreen mode

With Filter:



let passedStudents = marks.filter((mark) => mark > 35).length; // 5


Enter fullscreen mode Exit fullscreen mode

Example 2: Find dogs from the given array

Return the array of animal which has species dog



let animals = [
    { name: "FluffyKins 🐇", Species: "rabbit" },
    { name: "DexLuthor 🐕", Species: "dog" },
    { name: "Trenton 🐕", Species: "dog" },
    { name: "Joey 🐕", Species: "dog" },
    { name: "FetchFishy 🐟", Species: "fish" },
    { name: "Dianna 🐟", Species: "fish" },
    { name: "CatePurry 🐈", Species: "cat " },
    { name: "BobBear 🐻", Species: "bear" },
    { name: "Todd 🐻", Species: "bear" },
    { name: "AlexLeon 🦁", Species: "lion" },
];


Enter fullscreen mode Exit fullscreen mode

Without using Filter:



let dogsFor = [];
for (let i = 0; i < animals.length; i++) {
    if (animals[i].Species == "dog") {
        dogsFor.push(animals[i]);
    }
}

console.log(dogsFor);

//Output:
[
    { name: "DexLuthor 🐕", Species: "dog" },
    { name: "Trenton 🐕", Species: "dog" },
    { name: "Joey 🐕", Species: "dog" },
];


Enter fullscreen mode Exit fullscreen mode

With Filter:



const dogs = animals.filter((animal) => animal.Species === "dog");

//Output:
[
    { name: "DexLuthor 🐕", Species: "dog" },
    { name: "Trenton 🐕", Species: "dog" },
    { name: "Joey 🐕", Species: "dog" },
];


Enter fullscreen mode Exit fullscreen mode

3. Reduce

This can be the most confusing method in the bunch, its just has lots of parameters. Basically we are taking a iterable array or object and converting it to a single value. Normally we have to use the accumulator(it can be an array or the value 0) for storing the data, but reduce method gives us this accumulator out of the box. It is the first parameter in the callback function, and the initial value of this accumulator is provided after the function callback inside round braces.

Reduce method executes a reducer function that you provide as a callback and returns a single output. In other words it takes the iterable and reducer function then return a reduced value.

Reducer comes with some terminology such as reducer and accumulator.

  • The accumulator is the value that we end with and the reducer is what action we will perform in order get to one value.
  • accumulator is just a fancy word for an empty array or zero.
  • Reduce will return one value and one value only hence the name is reduce

Syntax:

Regular JS:



let newArr = arr.reduce(function (accumulator, currentVal, index, currentArr) {
    //Reducer function
}, initialValue);


Enter fullscreen mode Exit fullscreen mode

Using ES6 arrow functions:



let newArr = arr.reduce((accumulator, currentValue, index, currentArray) => {
    //Reducer logic
}, initialValue);



Enter fullscreen mode Exit fullscreen mode
  • function: This will be callback function which checks the condition if its true or false for each item
  • accumulator: The accumulator accumulates callback's return values. It means its stores all the values returned by callback. It can be a number, array or object.
  • currentValue: Current value is similar to arr[i] when we iterate over array using for loops
  • index: Current index of the item
  • currentArray: the array we are iterating over. In this case its "arr"

  • newArr: will return a new reduced array.

  • initialValue: A value to use as the first argument to the first call of the callback.
    Further Reading:

Example 1: Find the sum of the provided numbers



let scores = [99, 45, 67, 35, 76, 29, 78, 83, 69, 88];


Enter fullscreen mode Exit fullscreen mode

Without using Reduce:



let avg = 0;

function avgFor(arr) {
    for (i = 0; i < arr.length; i++) {
        avg += arr[i];
    }
    return avg;
}

console.log(avgFor(scores)); // 669


Enter fullscreen mode Exit fullscreen mode

Wit Reduce:



let avg = scores.reduce((sum, score) => sum + score);
console.log(avg); //669


Enter fullscreen mode Exit fullscreen mode

Example 2: Find the average salary of the given employees



let EmployeesObject = {
    Employees: [
        {
            userId: "rirani",
            jobTitleName: "Developer",
            firstName: "Romin",
            lastName: "Irani",
            preferredFullName: "Romin Irani",
            employeeCode: "E1",
            salary: 75000,
            region: "CA",
            phoneNumber: "408-1234567",
            emailAddress: "romin.k.irani@gmail.com",
        },
        {
            userId: "nirani",
            jobTitleName: "Database Admin",
            firstName: "Neil",
            lastName: "Irani",
            preferredFullName: "Neil Irani",
            employeeCode: "E2",
            region: "CA",
            salary: 90000,
            phoneNumber: "408-1111111",
            emailAddress: "neilrirani@gmail.com",
        },
        {
            userId: "thanks",
            jobTitleName: "Program Directory",
            firstName: "Tom",
            lastName: "Hanks",
            preferredFullName: "Tom Hanks",
            employeeCode: "E3",
            region: "CA",
            salary: 150000,
            phoneNumber: "408-2222222",
            emailAddress: "tomhanks@gmail.com",
        },
        {
            userId: "draks",
            jobTitleName: "Full Stack Developer",
            firstName: "Drake",
            lastName: "Smith",
            preferredFullName: "Drake Smith",
            employeeCode: "E3",
            region: "CA",
            salary: 150000,
            phoneNumber: "408-2222222",
            emailAddress: "tomhanks@gmail.com",
        },
    ],
};


Enter fullscreen mode Exit fullscreen mode

Storing employees array in a variable. finding the sum of the salary and storing it in an accumulator which initializes at 0, and finally dividing it by salaries length which will give us an average salary



const salaries = EmployeesObject.Employees;

const avgSalary =
    salaries.reduce((avg, employee) => avg + employee.salary, 0) /
    salaries.length;


// Output
console.log(avgSalary); // 116250


Enter fullscreen mode Exit fullscreen mode

Conclusion: I've just scratched a surface using on the functional programming part, JS has many other methods which comes under functional programming, But I think these are the main ones. My react journey has been very easy because of these methods and overall JS too. I encourage you to master these methods so you can write efficient JS code. Thanks for reading. Follow me on github I post well documented code with various examples on m github .

Further Reading:

Functional Programming

Programming Paradigms

Video links:

Learning functional programming (JS conf)

Fun fun function's playlist

Connect with me:




Top comments (0)