Introduction to Linux - A Hands on Guide | Linux Bible | Linux From Scratch | A Newbie's Getting Started Guide to Linux | Linux Command Line Cheat Sheet | More Linux eBooks



Tuesday, 20 December 2016

Python reduce() Function

Python reduce() Function - In one of the recent articles, we have learned about anonymous function that can be created using lambda construct. Now we have been learning the functions which can be used along with lambda to ease things for us – which are map(), reduce and filter(). We have already covered map() function in our last article and in this article, we will learn about reduce() function. Let’s begin with the discussion straight away.


Using reduce() with lambdas

As we learned in our article on map() function, it receives minimum of two arguments – a function and one or more iterable objects, and run the function on each element of the iterable. It returns a list object containing the result of the computation. In the same manner, reduce accepts a function, with two arguments and an iterable. It then applies the function on the iterable elements from left to right and returns a single value.

Of the two arguments in the function, say lambda x, y : x + y, first value x is the accumulator, which stores the result of the operation and is updated at each step. While the second value y is the item from the iterable. We also have an optional third argument initializer to the reduce() function, which can be considered as the default accumulator value or it can be thought as if it is placed before first element in the iterable. As a result, when we provide an empty iterable and an initializer, we get default value returned. If initializer is not mentioned, x takes the value of first item in the iterable and y starts iterating from second item onwards.

Don’t panic if it seems confusing. We will work on some examples and dig them deeper. Let’s start with simpler example at first.

Syntax:

reduce( function, iterable [, initializer] )

Example :

# Create the iterable object containing numbers
>>> myList = range(1, 11)
>>> myList
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Our lambda function return addition on two numbers
>>> lambda x, y: x + y

# We use our lambda function and the iterable in 'reduce()' function
>>> print reduce( lambda x, y: x + y, myList )
55

How it works

In the above example, we have not used the initializer. Due to this, for the first time, x is assigned with the first value in the iterable, so x = 1. Now, y starts iterating from second item in the iterable onwards. Thus, in the first iteration, x = 1 and y = 2. With this, we call our lambda function, which returns the sum 1 + 2 = 3. Now, for the second iteration, result value is stored in x, so x = 3 and y gets the next item, means y = 3. Function gets called with this and returns 3 + 3 = 6. For next iteration, x = 6 and y = 4, the next item from the iterable, and this continues till we get the final result.

# Analysis

myList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Iteration - 1
x = 1  -> 1st list item
y = 2  -> 2nd list item
result = 3

# Iteration - 2
x = 3  -> Result from last iteration
y = 3  -> 3rd list item
result = 6

# Iteration - 3
x = 6  -> Result from last iteration
y = 4  -> 4th list item
result = 10

# Iteration - 4
x = 10  -> Result from last iteration
y = 5  -> 5th list item
result = 15

# Iteration - 5
x = 15  -> Result from last iteration
y = 6  -> 6th list item
result = 21

# Iteration - 6
x = 21  -> Result from last iteration
y = 7  -> 4th list item
result = 28

...
...
...

# Last iteration
x = 45  -> Result from last iteration
y = 10  -> 10th list item
result = 55  -> Final result

We now use third argument in reduce() function - Initializer. With the same example, we assign the value 1000 to the initializer.

>>> sum = lambda x, y: x + y
>>> sum
<function <lambda> at 0x7fcfc9c7bcf8>

>>> print reduce( sum, myList, 1000 )
1055

# Analysis

myList = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Iteration - 1
x = 1000  -> Initializer
y = 1  -> 1st list item
result = 1001

# Iteration - 2
x = 1001  -> Result from last iteration
y = 2  -> 2nd list item
result = 1003

# Iteration - 3
x = 1003  -> Result from last iteration
y = 3  -> 3rd list item
result = 1006

# Iteration - 4
x = 1006  -> Result from last iteration
y = 4  -> 4th list item
result = 1010

...
...
...

# Last iteration
x = 1045  -> Result from last iteration
y = 10  -> 10th list item
result = 1055  -> Final result

As we can observe from the result we’ve got, initializer value has made the difference. We now see another example of product of the numbers in the list, using reduce function. There will be only one change, that too in our lambda function.

# lambda function
>>> product = lambda x, y: x * y

# Iterable object
>>> myList
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Result of 'reduce()' function
>>> print reduce( product, myList )
3628800

# Verifying the result - It's a factorial, isn't it?
>>> 1 * 2 * 3 * 4 * 5 * 6 * 7 * 8 * 9 * 10
3628800

In Python, we have operator module that provides functions equivalent to built-in arithmetic (like +, -, /, *) and logical operations (like and, or, not). So, for addition, we have operator.add, for multiplication, we have operator.mul, and so on. You can check all available options by importing operator module and then running dir(operator). For now, we stick to our examples and use functions from operator module in place of lambda function.

>>> import operator

>>> myList
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

# Addition
>>> print reduce( operator.add, myList )
55

# Product / Multiplication
>>> print reduce( operator.mul, myList )
3628800

We can also have a list of string as the iterator object, for which operator.add would return concatenated value of string items, as + operator concatenates two strings. Whereas operator.mul, just like * operator, will do the repetition of the string.

# String Concatenation with '+' operator and 'operator.add'

>>> myList = ['My', 'Name', 'Is', 'Bond', ',', 'James', 'Bond' ]

>>> print reduce( operator.add, myList )
MyNameIsBond,JamesBond

>>> print reduce( lambda x , y : x + y, myList )
MyNameIsBond,JamesBond

# String Repetition with '*' operator and 'operator.mul'

>>> myList = ['String ', 1, 2, 3]

# It will print 'String' 6 (1*2*3) times
>>> print reduce( operator.mul, myList )
String String String String String String

>>> print reduce( lambda x, y : x * y, myList )
String String String String String String

With this, we end our discussion on reduce() function. Its syntax is just like map() function, but where map() returns a list, it returns a single value. In the next article, we will be learning about another important function useful in functional programming - filter(). Please share your views and feedback in the comment section below and stay tuned. Thanks.


0 comments:

Post a Comment