Functional Programming: Reduce() Function in Python
Reducing sequence to a single output value!
In the previous string of articles, I have talked about the importance of immutable data structures in functional programming. I have also covered the filter() function in the last article.
Let’s start from where we left. In this article, I will be talking about the reduce() function.
Working with reduce() function
Just like the filter() function, reduce is another FP aka functional programming primitive that you can use in your Python code. The documentation defined reduce() function as:
“Apply function of two arguments cumulatively to the items of sequence, from left to right, so as to reduce the sequence to a single value.”
reduce(function, iterable[, initializer]): Looks like reduce() takes a function and an iterable (sequence of stuff). Although an initializer can also be given as a parameter and is placed before the items of the sequence in the calculation.
For example, reduce(lambda x, y: x+y, [1, 2, 3, 4, 5]) calculates ((((1+2)+3)+4)+5). The left argument, x, is the accumulated value and the right argument, y, is the update value from the sequence.
It might seem a lot to grab. For a beginner, reduce() function gives us a descriptive value (eg. sum). It reduces a sequence to a single output value.
reduce(lambda x, y: x+y, [1, 2, 3, 4, 5])
[Output]: 15
The above line of code took a lambda function and calculated the sum of the sequence given as a parameter. “x” is the accumulated value from each iteration and “y” is the new value. In the end, it gave us the sum of the sequence.
Now that you have got the gist of the reduce() function. It’s time to bring our last problem in the picture and work with it only. Our dataset consists of GOT characters — name, profession, and experience.
got_chars=(
got_char("name":"John","profession":"King's Hand","experience_in_year":3),
got_char("name":"Arya Stark","profession":"No One","experience_in_year":4),
got_char("name":"Sansa Stark","profession":"Queen Winterfell","experience_in_year":1),
got_char("name":"Danaerys","profession":"Queen","experience_in_year":3)
)
So, I want to extract the average experience of all the GOT characters.
reduce(lambda acc, char: acc+char, got_chars)/len(got_chars)
[Output]: 2.2
The reduce() function above has a lambda expression which takes two arguments- an accumulator (acc) and the value(char). Another parameter is the sequence i.e got_chars in the function. So, the function will return the sum of experience that will be divided by the length of a tuple. Hence, the mean value of the experience will be returned.
If you want to bring an optional argument in the picture i.e initializer. You can do it like this.
reduce(lambda acc, char: acc+char, got_chars,0)/len(got_chars)
[Output]: 2.2
In this line, I have initialized our accumulator (acc) as 0. By default, the accumulator value is zero but you can initialize the accumulator with any value.
Grouping values using reduce()
There is a lot more to do with reduce() function. Let’s say, you want to group your dataset by gender of the character.
got_chars=(
got_char("name":"John","profession":"King's Hand","experience_in_year":3, "sex":"M"),
got_char("name":"Arya Stark","profession":"No One","experience_in_year":4, "sex":"F"),
got_char("name":"Sansa Stark","profession":"Queen Winterfell","experience_in_year":1, "sex":"F"),
got_char("name":"Danaerys","profession":"Queen","experience_in_year":3, "sex":"F")
)
Now, we want our characters to be grouped in “M” or “F”. For it, I have created a function below.
def reduce_fun(acc,char):
acc[char.sex].append[char.name]
return accreduce(reduce_fun, got_chars, {'M':[],'F':[]})
I have initialized an accumulator which is a dictionary with “M” and “F” keys. Those keys can take a list of names. For that, I have defined the reduce_fun function which appends the name to the list according to keys of the dictionary. And, the output looked like this.
[Output]: {'M': ['John'],
'F': ['Arya Stark', 'Sansa Stark', 'Danaerys']}
One thing, I really don’t like about this is that I had to define an accumulator like this.
{'M':[],'F':[]}
To overcome this problem, I imported the defaultdict from collections and create the same result.
from collections import defaultdict
reduce(reduce_fun, got_chars, defaultdict([list]))
Now, if I run this piece of code, I will get the same output.
defaultdict(<class 'list' >,
{'M': ['John'],
'F': ['Arya Stark', 'Sansa Stark', 'Danaerys']})
Summary
In this post, I have talked about how you can use reduce() function in your Python code. The reduce() function is basically functional programming primitive that helps in reducing a sequence of numbers to a single output value. In the post, I have used the reduce() function to get an accumulated result and for grouping the result.
Reference
Peace!