Higher Order Functions with Reduce
Tags: javascript, codenewbie
Published: 2021-01-17 06:34:43



Reduce is one of my favorite higher order functions in javascript array object, I have tried to recreate other commonly used higher order functions using reduce just for fun (also I did not find any such existing implementation examples in one post). In this blog, I will re-create the following higher order functions of the array object using reduce.
<ol>
	<li>Map</li>
	<li>Filter</li>
	<li>Find</li>
	<li>Every</li>
	<li>Some</li>
</ol>

I will be using simple examples to make it easier to understand. So lets get started!


## Map

The **`map()`** method **creates a new array** populated with the results of calling a provided function on every element in the calling array.

We can use map function to perform some operation on each element in the array. In the below example, we will be using map to square each element in the array.
```js
let sampleArray = [1,2,3,4,5,6,7,8,9,10];

let mapResult = sampleArray.map(current=> current * current);
```

If we try to log the result we will get the following result.
```bash
[1,  4,  9,  16,  25,  36,  49,  64,  81,  100]
```
Now lets implement the same functionality using reduce. 
```js
let reduceResult = sampleArray.reduce((acc, curr)=> [...acc, curr * curr], []);
```
If you log the result, you will see that you get the same result. Now lets move on to <strong>filter</strong>.

## Filter

The **`filter()`** method **creates a new array** with all elements that pass the test implemented by the provided function.

We can use the  `filter()` function to remove the unwanted elements from the array. Basically filter takes a callback function which returns a boolean value. This callback function is called on each element of the array. Which ever element returns false for the callback function will be removed from the resulting array.

In the below example, from an array of numbers 1-10, I will be removing the elements which are less then five using filter function.
```js
let sampleArray = [1,2,3,4,5,6,7,8,9,10];

let filteredArray = sampleArray.filter(current=>current > 5)
```
If we log this we will get the below result.
```bash
[6,  7,  8,  9,  10]
```
With reduce, the same functionality can be achieved with a little bit more lines of code.
```js
let reducedFilterArray = sampleArray.reduce((acc, curr)=> {
  if(curr > 5){
    return [...acc, curr];
  } else 
    return acc;
},[]);
```
The result will be same as the one with  `filter()` function.

So far, <em>filter</em> and <em>map</em> have been pretty simple to implement with reduce with only few extra lines of code. Now lets look into more complex functions starting with <strong>find</strong>.

## Find

The **`find()`** method returns the value of the <em>first</em> element in the provided array that satisfies the provided testing function. If no values satisfies the testing function, <em>undefined</em> is returned.

**`find()`** method takes a callback function and and executes the function on each element of the array. If it finds the element that satisfies the callback function it returns the element and stops the execution. As the name suggests, this method is used to find a element. If it does not find any elements to satisfy the condition it will return <em>undefined</em>.  Lets look at an example.
```js
let sampleArray = [1,2,3,4,5,6,7,8,9,10];

let findResult = sampleArray.find(current => current > 5);
```
So in this example, we are going to find the first element that is greater then five. Lets log to see the result of the function. If you thought 6 then congratulations, you are right! 
```bash
6
```
So there are two things that `find()` does essentially, first is to return the first element that satisfies the condition and the second is to return undefined if none of the elements satisfies the condition. Now the problem when we try to implement this with reduce is that reduce takes effect on each element in the array and there is no way to stop it once the first elment is found. So, I used my big brains and came up with the following solution to this problem
```js
let reduceResult = sampleArray.reduce((acc, curr)=> {
  if(curr > 5) {
    if(acc){
      return acc;
    } else {
      return curr;
    }
  } else {
    return undefined
  }
}, undefined);
```
Let me walk you through the solution here. First of all, I am setting the inital object to <em>undefined</em> so that if we use it on an empty array we will get the same result as find. Second, I am using a condition to return the result, the condition being if there is some value in the result we will not assign any other value to it. This is to prevent the next values passing the condition to overwrite the first matching value. Now if you log this result you will see that the results are same as that of find. 

## Every

The **`every()`** method tests whether all elements in the array pass the test implemented by the provided function. It returns a Boolean value.

 **`every()`** method returns true if every element in the array satisfies the callback function, otherwise it returns false. So even if a single element does not match the condition, it will return false. Typically we will use `every()` to validate some data. In the below example I am having 2 data sets and i am checking if all the elements in my array are less then 11.
```js
let sample1Array = [1,2,3,4,5,6,7,8,9,10];
let sample2Array = [2,5,7,9,11,13,15];

let everyTrue = sample1Array.every(current=> current < 11);
let everyFalse = sample2Array.every(current=> current < 11);
``` 
For this example the `sample1Array` will return the result as true and `sample2Array` will return false.
```bash
sample1Array -> true
sample2Array -> false
```
So how do we implement this with reduce? Big brain time again! By using the learnings of the previous 3 methods i was able to achieve this with the below code.
```js
let reduceTrue = sample1Array.reduce((acc, curr)=> { 
  if(curr < 11){
    return true
  } else 
    return false
}, true);

let reduceFalse = sample2Array.reduce((acc, curr)=> { 
  if(curr < 11){
    return true
  } else 
    return false
}, true);
```
I will not walk through this code as its pretty similar to what we did with `find()`.

## Some
The **`some()`** method tests whether at least one element in the array passes the test implemented by the provided function. It returns a Boolean value.

`some()` is kind of opposite of what `every()` is in the sense if returns true if any element in the array satisfies the condition of the callback function and false only if none of the elment satisfy. For this example, I am reversing the condition of the example i used for `every()`.
```js
let sample1Array = [1,2,3,4,5,6,7,8,9,10];
let sample2Array = [2,5,7,9,11]

let someFalse = sample1Array.some(current=> current > 10);
let someTrue = sample2Array.some(current=> current > 10);
```
So here, we will get the result of `sample1Array` as false and `sample2Array` as true. So the implementation for this using reduce will also be very similar to what we have done with `every()` with slight changes.

```js
let reduceFalse = sample1Array.reduce((acc, curr)=> {
  if(curr > 10){
    return true;
  } else 
    return acc;
}, false);

let reduceTrue = sample2Array.reduce((acc, curr)=> {
  if(curr > 10){
    return true;
  } else 
    return acc;
}, false);
```
If we log the results we will see that results for both the functions are same.
```bash
sample1Array -> false
sample2Array -> true
```

# Conclusion

First of all, if you guys are still here then a big thanks to all of you. This blog turned out to be longer then I expected. Also, there is no real conclusion here, just wanted to show the power of reduce. Now if you ask me should I use reduce for every situation, the answer will be a big NO. But its handy to know that if we want, we can do all this with reduce.

Last thing I would like to say is the definition of all the functions have been taken from MDN. Its a great site for more information on all the functions and web in general.