Map, Filter and Reduce

  • enables functional programming in Python

  • map and filter are built-ins (__builtins__).

  • reduce needs to be imported from functools module

map()

  • Syntax:

    map(function, iterable, ...)

  • In simple terms, above syntax can also be written as:

    map(function_to_apply, input_list)

  • Here, function (or function_to_apply) is a function on which each element in iterables (list, set, …) are applied.

  • Lets have a look at the code below:

Note: Checkout lambda from previous sections.

# List of squared numbers using loop
numbers = [1, 2, 3, 4, 5]
squared_numbers = []

for number in numbers:
    squared_numbers.append(number ** 2)

print("Loop:",squared_numbers)
Loop: [1, 4, 9, 16, 25]
# List of squared numbers using map and lambda function
numbers = [1, 2, 3, 4, 5]
squared_numbers = list(map(lambda number: number**2, numbers))

print("map and lambda function:",squared_numbers)
map and lambda function: [1, 4, 9, 16, 25]
# List of squared numbers using map and function
def square(number):
    return number**2

numbers = [1, 2, 3, 4, 5]
squared_numbers = list(map(square, numbers))

print("map and function:", squared_numbers)
map and function: [1, 4, 9, 16, 25]

More examples:

# detect even odd numbers:
numbers = list(range(0, 10))

is_even_odd = list(map(lambda number: True if number % 2 == 0 else False, numbers))

print(dict(zip(numbers, is_even_odd)))
{0: True, 1: False, 2: True, 3: False, 4: True, 5: False, 6: True, 7: False, 8: True, 9: False}

filter()

  • Syntax:

    filter(function, iterable)

  • Compared to map(), ony one iterable is required.

  • filter() returns a list of elements for which the applied function returns True.

  • Lets have a look at the code below:

Note: Checkout lambda from previous sections.

# filter even numbers:
numbers = list(range(0, 10))

even_numbers = list(filter(lambda number: number % 2 == 0, numbers))

print(even_numbers)
[0, 2, 4, 6, 8]
# calculate grade
scores = [50, 90, 68, 88, 85, 76, 77, 66, 68]

scores_over_75 = list(filter(lambda score: score > 75, scores))

print("Grade A:",scores_over_75)

scores_over_60 = list(filter(lambda score: score > 60 and score < 75, scores))

print("Grade B:",scores_over_60)
Grade A: [90, 88, 85, 76, 77]
Grade B: [68, 66, 68]
# find pallindrome words from a list of words
words = ["anna", "complete", "rank", "radar", "progress", "level"]

pallindrome_words = list(filter(lambda word: word == word[::-1], words))

print("Pallindrome words are: ",pallindrome_words)
Pallindrome words are:  ['anna', 'radar', 'level']

reduce()

  • Returns a single value unlike map() and filter()

  • Can be imported from functools module

  • Syntax:

    reduce(function, iterable[, initializer])

  • In above syntax, First parameter function is the function on which each element in the iterable gets cumulatively applied to.

  • initializer is the optional value, when present, is placed before the items of the iterable.

  • Lets have a look at the code below:

Note: Checkout lambda from previous sections.

# Sum of numbers using look
sum = 0
numbers = list(range(1, 10))
for number in numbers:
    sum = sum + number

print("Sum using loop:", sum)
Sum using loop: 45
from functools import reduce

# Sum of numbers using reduce
numbers = list(range(1, 10))
sum = reduce(lambda num1, num2: num1 + num2, numbers)

print("Sum using reduce:", sum)
Sum using reduce: 45
from functools import reduce

# Sum of numbers using reduce with optional initial value
numbers = list(range(1, 10))
sum = reduce(lambda num1, num2: num1 + num2, numbers, 10)

print("Sum using reduce and initial value:", sum)
Sum using reduce and initial value: 55
from functools import reduce

# Sum of numbers using reduce with optional initial value
numbers = []
sum = reduce(lambda num1, num2: num1 + num2, numbers, 10)

print("Sum using reduce and initial value:", sum)
Sum using reduce and initial value: 10

In the above example, the initializer 10 serves as a default when the iterable numbers is empty. So the result becomes 10.

Combining map(), filter() and reduce()

  • It is possible to use these function along side each other.

  • For instance, have a look at the code below:

# Square of numbers greater than 5
numbers = list(range(0, 10))

squared_numbers = list(
    map(lambda number: number ** 2, filter(lambda number: number > 5, numbers))
)

print("Numbers:", numbers)
print("Squared numbers(> 5):", squared_numbers)
Numbers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Squared numbers(> 5): [36, 49, 64, 81]
from functools import reduce

# Sum of square of numbers greater than 5
numbers = list(range(0, 10))

sum_squared_numbers = reduce(
    lambda num1, num2: num1 + num2,
    map(lambda number: number ** 2, filter(lambda number: number > 5, numbers)),
)

print("Numbers:", numbers)
print("Sum of squared numbers(> 5):", sum_squared_numbers)
Numbers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Sum of squared numbers(> 5): 230

Above example can also be written as:

from functools import reduce

# Sum of square of numbers greater than 5
numbers = list(range(0, 10))

squared_numbers = list(
    map(lambda number: number ** 2, filter(lambda number: number > 5, numbers))
)

sum_squared_numbers = reduce(lambda num1, num2: num1 + num2, squared_numbers)

print("Numbers:", numbers)
print("Squared numbers(> 5):", squared_numbers)
print("Sum of squared numbers(> 5):", sum_squared_numbers)
Numbers: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
Squared numbers(> 5): [36, 49, 64, 81]
Sum of squared numbers(> 5): 230