28 Jun 2021 13 min read
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.
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.
Imperative programming works by changing the program state through assignment statements. The main focus in this approach is how we achieve the goal
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.
Declarative programming is a way of building programs that express the logic of computation without describing its control flow.
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.
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.
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.
Regular JS:
let newArr = arr.map(function (currentValue, index, currentArray) {
//logic for new array
})
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;
})
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.
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 ]
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 ]
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.
// Input:
const arr = [0, 1, 2, 3, 4, 5]
// Output:
// [ 0, 2, 4, 6, 8 ]
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 ]
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 ]
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",
},
],
}
// 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",
]
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.
Regular JS:
let newArr = arr.filter(function (currentValue, index, currentArray) {
//Condition for new array
})
Using ES6 arrow functions:
let newArr = arr.filter((currentValue, index, currentArray) => {
// Condition for new array
})
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]
Without using Filter:
let passed = 0
for (let i = 0; i < marks.length; i++) {
if (marks[i] > 35) {
passed++
}
}
console.log(passed) // 5
With Filter:
let passedStudents = marks.filter(mark => mark > 35).length // 5
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" },
]
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" },
]
With Filter:
const dogs = animals.filter(animal => animal.Species === "dog")
//Output:
;[
{ name: "DexLuthor 🐕", Species: "dog" },
{ name: "Trenton 🐕", Species: "dog" },
{ name: "Joey 🐕", Species: "dog" },
]
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.
Regular JS:
let newArr = arr.reduce(function (accumulator, currentVal, index, currentArr) {
//Reducer function
}, initialValue)
Using ES6 arrow functions:
let newArr = arr.reduce((accumulator, currentValue, index, currentArray) => {
//Reducer logic
}, initialValue)
let scores = [99, 45, 67, 35, 76, 29, 78, 83, 69, 88]
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
Wit Reduce:
let avg = scores.reduce((sum, score) => sum + score)
console.log(avg) //669
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",
},
],
}
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
Learning functional programming (JS conf)