ELI5 - "Map-filter-reduce" 
Tags: explainlikeimfive, programming, beginners, discuss
Published: 2017-12-04 10:12:14

---
title: ELI5 - "Map-filter-reduce" 
published: true
description: 
tags: explainlikeimfive , programming, beginner, discuss
---

Many developers that I have lately interacted with associate map-reduce-filter with functional programming, and they are actually dreaded by the combination. It’s one of the reasons they avoid using functional languages, because **god forbid they would have to learn how to use map, reduce and filter** — 3 functions present in Ruby, Python, Javascript, PHP, Erlang, Scala and many others languages.

__So what’s the big deal with map-reduce-filter anyway?__

> They are just higher-order functions used in functional programming. And they work on anything that is iterable (list, tuple, sets, dicts, and even strings).

Let’s consider a problem statement to be able to follow more clearly. (We’re using Python for the ease of purpose, but I’ll add a gist of how the same thing can be done in various other languages)

**Problem statement : 
We need the sum of all even squares of integers in the range [0, 9]**

### Map (Transform)

This function takes a unary function and a list. Unary function is a function that takes one variable. The resultant for map function is a same-sized list of transformed values. The transformation of value is subject to the definition of unary function with the parameter. 

**Use when** : You want to transform all elements in a set to another set of values.

**Parameters** : unary transformation function & array to be transformed

In order to solve the problem statement, let’s say, our first step is to map the function of calculating squares over the range of numbers [0, 9]

```bash
>>> nums = map(lambda x : x*x, [i for i in range(10)])
>>> nums
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
```

Lambdas are often to define map functions. You can use regular functions as well.

### Filter 

This function takes a predicate, (a unary function which returns a bool) and the set of values; and gives a resultant set with only those set of values for which the predicate returns true. The resultant set may or may not be of the same length. 

**Use when** : You want to remove elements from a set based on a condition. 

**Parameters** : unary predicate (should only return a bool) & array to be filtered. 

In context to our problem above, let’s try to remove all the odd squares from the list. For that, let our predicate return true if the element is even. 

```bash
>>> def is_even(x):
        return x % 2 == 0
>>> evens = filter(is_even, nums)
>>> evens
[0, 4, 16, 36, 64]
```

Comprehensions often make it easier to write filters. Those can be used in place of functions as well.

### Reduce (Accumulate)

This function takes a binary function and a set of values, and it produces a single value. It does so by running the binary function over the set of values, and accumulating them into a single value. 

**Use when** : You want an accumulated or concatenated value using given set of values.

**Parameters** : binary function and set of values.

In context to our problem above, we shall add up all the even-valued squares.

```bash
>>> reduce(lambda x,y : x+y, evens)
120
```

If we look at the defintion of reduce in functools module,

```python
def reduce(f,alist)
    if alist == []:
        return None

    answer = alist[0]
    for v in alist[1::
        answer = f(answer,v)
    return v
```

we see that reduce function starts by setting answer as the first element of array. Then it traverses the array from left to right, invoking a callback function on each element. The cumulative value is passed from callback to callback. After all elements are traversed, cumulative value is returned. 

### Combining map-filter-reduce

We saw a lot of small functions being written above, that was just for understanding. The true power of higher-order-functions lie in combination. So our problem statement can be solved in one line of code 😅

```bash
>>> reduce(lambda a, b: a + b, map(lambda x: x * x, filter(lambda y: not y % 2, range(10))))
120
```

Don’t Panic! ! We can break it down for simplicity. 

```python
f_add = lambda a, b: a + b
f_square = lambda x: x * x
f_is_even = lambda y: not y % 2
```

Now the complex expression can be rewritten as 

```bash
>>> reduce(f_add , map(f_square , filter(f_is_even, range[0, 10]))
```

__As a sidenote, there is no restriction on using map , filter & reduce together. You can make your own combinations, and order your functions as per the need.__

### Other languages 

Keeping the problem statement same as above, check out how map-reduce-filter can be used in other programming languages, and is not a rocket science at all 🚀

#### Ruby

```ruby
def main()
    
    nums = [*0..9]
    
    ans = nums.map{|x| x * x}              # map operation (x*x) over nums
              .select{|x| x % 2 == 0}      # select event elements
              .reduce{|a, x| a + x}        # reduce the list by `+` operation
    
    p nums                                 
    p ans                                  
    
end
main()
```

#### Clojure

```clojure
(reduce (fn [a b] (+ a b)) 
        (map (fn [x] (* x x)) 
             (filter even? (range 10))))
```

#### Javascript
(I’m really bad at this 😕)

```javascript
let numbers = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

ans = numbers 
    .filter(function(num) {
        return (num%2 === 0);
    })
    .map(function(num) { 
        return num*num;
    })
    .reduce(function(total, num){
        return total += num;
    });

```

Try it out in other languages as well!