Combining map() With reduce()
Here are resources and additional documentation about the operator module and operators:
00:00
Let’s now talk about combining the map()
function with the reduce()
function. The reduce()
function is another important function in functional programming, and in Python, it’s contained in the functools
module. Just like the filter()
function, it takes two positional arguments.
00:17 The first one is a function. It’s any callable that accepts two arguments and returns a value. The second argument is any Python iterable.
00:28
The idea with the reduce()
function is that it’s going to recursively apply the function to the items in the iterable and return a final value.
00:37
I’ll talk about this idea of recursively applying the function in the next slide. So, for example, let’s suppose we have this iterable of a list containing four elements a
, b
, c
, and d
, then a call to the reduce()
function with the function f()
is simply going to be obtained as follows.
00:57
We first apply the function f()
to the first two elements of the iterable, a
and b
. Then we take that return value as the first positional argument to another call of f()
with the second positional argument being the third element of the iterable—in this case, c
. Then we take that return value as the first positional argument to another call with the function f()
and the second positional argument being the last element of the iterable—in this case, d
. So, for example, if the function is just simple addition of elements, which—depending on the context—may not just be addition of numbers, then a call to the reduce()
function will take f()
and simply return a + b
, and then that as the first positional argument to the sum with c
, and then that return value as the first positional argument, adding it up to d
.
01:55
So, the way to think about the reduce()
function is that it applies the function from left to right, taking two arguments at a time. The first two arguments are going to be the first two elements of the iterable, and then take that return value and apply it with the third element of the iterable and so on.
02:14
That is the idea of this recursive nature of the reduce()
function.
02:21
reduce()
also accepts a third parameter. It’s optional and it’s usually called the initializer
and it’s going to provide a seed value to the computation or it serves as a default value when the iterable is empty. And by seed value we mean that it’s going to serve as the first positional argument on the left of the first call to the reduce()
function and the second argument will be the first element of the iterable.
02:48
So, the idea is that we’re sort of adding to the iterable on the left this first value placed in the initializer
argument, and then the computation will continue just as it would.
03:00
If the iterable is empty, then the reduce()
function will simply return this seed value.
03:07
It’s worth noting before we jump into an example that the reduce()
and filter()
functions of course can be applied on their own without having to combine them with the map()
function.
03:16 But frequently, you are doing some sort of reduce operation or some sort of filter function and then you want to map some other function on that result or vice versa.
03:27
Maybe first you want to do some sort of mapping of a function on an iterable and then either apply the reduce()
method or the filter()
function, and so a lot of times you may want to combine these two functions. All right, let’s jump to the example.
03:42
We’re going to use the reduce()
function to solve a problem that you’ve probably had to solve before, and that is in flattening out a list—a nested list. So, let me pull up a list here.
03:54 This list is going to contain lists as its elements and the sub-lists are lists that contain strings, and the strings contain digits.
04:05 The problem that you want to solve is you want to only extract from this list the unique elements or the unique numbers represented by these strings and you want to convert them into integer data types.
04:20
So at the end of the day, what you want is either maybe an iterator or maybe a list that would contain, for example, the number 12
, the number 33
, the number 54
, and 33
is included already, so -1
, 12
, and then 32
as well, right?
04:37 So, that’s the idea: extract all of the elements from the list that are unique, or just keep the only unique copies of them, and just make them into integers. Now, there’s a lot of ways for you to do this but let’s just do this using function calls so that we sort of remain in the spirit of functional programming.
04:58
The way I’m thinking of doing this is why don’t we first flatten out this list? And if you think about the operation of flattening out a list, you can think of it as a reduce()
call because whenever I add to a list, I’m concatenating them. And so if I add the first two, it basically creates a list containing the first two lists, and then I take that list and I add it to the third, and that would create a list containing all of these elements in the first three lists, and then I take that list and I add it to the last one.
05:33 And then at the end of the day, I’m left with a flattened-out list.
05:37
Let’s import the reduce()
function, so from functools import reduce
.
05:45
And, abstractly, what we’re saying that we want to do to flatten out the list is to apply the addition operator (+
) on the iterable a
, right?
05:55
That is essentially what we just sort of discussed: this operation of flattening out is equivalent to applying the add operator by reducing the list via the add operator. Now, of course this is going to be a problem if we just call reduce()
like this, because we need a function object, right?
06:15
We need a function that does addition. Now, we can write our own lambda
function to do this but maybe this is a good time—if you haven’t had a chance to explore the operator
module—to use the add()
function contained in the operator
module. And the operator
module, it contains a whole bunch of functions, sort of the basic intrinsic operators that are used all over in Python. So when you’re doing comparisons, you’re using the less than or equal operator (<=
), well, instead of using the symbol <=
you can call in the lt()
(less than) operator in the operator
module, right?
06:55 So instead of a symbolic thing, you use an actual function—a function object.
07:01
So, anyways, what we want to do is from the operator
module we want to import the add()
operator. And again, if you haven’t used the operator
module, there’ll be a link at the bottom here and you can check it out. So, let’s import add()
. All right.
07:17
So, what is the idea? We want to call reduce()
using the add()
operator on the list a
, and that should give us a flattened-out version of this list.
07:30
All right, there it is! We’ve got one single list and it’s been flattened out. That’s the return value of reduce()
. Now let’s go ahead and finish what it is that we wanted to do.
07:41
Let’s only keep the unique elements in that list. And again, there’s lots of ways to do this. Why don’t we use the set()
method? Because the set()
method will take that iterable, that list, and will create a set
out of it.
07:56
Any repetitions won’t be repeated because a set, by definition, is a container where all the elements are unique. And so that will create an iterable. It’ll be a set. Let’s now map the int()
function on that so that we obtain only integer data types at the end. All right!
08:15
And let’s just save that, say, in some variable b
.
08:20
All right! So, if all you want now is to iterate over b
, then you can just keep it as a map
object, but for us to see what happened here, let’s just call the list()
method on that. And there we go!
08:32
We’ve got this list that contains only the unique elements in the original nested list a
all as integer data types.
08:43
So, this is sort of a good example of what functional programming is about. You’re doing everything using function calls. The first thing we did was we reduce the list to get a single list that’s not nested, and then we keep only the unique elements in that single list using the set()
function, and then we map the integer built-in function so that we get just integers. Now, in some cases instead of using the reduce()
function, you’re better off using some of the built-in Python functions because you’ll end up getting a lot more readable code.
09:20
So, if you did actually want to sum some numeric data, then of course instead of using reduce()
and the add()
operator with a list of numbers, you would just call and use the sum()
function on that.
09:36 That’s a lot more readable—you know, less code! So, look out for different possible functions that are built into Python or that are just part of some of the modules that come with Python.
09:49
Maybe they solve a problem that you want to essentially do by some sort of reduction process. So again, alternative tools out there that you may want to try that are already part of the Python library. Okay! Well, that’s it on the reduce()
method. In the next lesson, we’re going to take a look at the starmap()
function, which you’ll see is very similar to the map()
function but has some very nice use cases that you’ll want to know about.
Become a Member to join the conversation.