Map, Filter, and Reduce are paradigms of functional programming. They allow the programmer (you) to write simpler, shorter code, without necessarily needing to bother about intricacies like loops and branching.
Essentially, these three functions allow you to apply a function across a number of iterables, in one fell swoop. map and filter come built-in with Python (in the __builtins__
module) and require no importing. reduce, however, needs to be imported as it resides in the functools module. Let's get a better understanding of how they all work, starting with map.
Map
The map()
function in python has the following syntax:
map(func, *iterables)
Where func is the function on which each element in iterables (as many as they are) would be applied on. Notice the asterisk(*) on iterables? It means there can be as many iterables as possible, in so far func has that exact number as required input arguments. Before we move on to an example, it's important that you note the following:
In Python 2, the map()
function returns a list. In Python 3, however, the function returns a map object which is a generator object. To get the result as a list, the built-in list() function can be called on the map object. i.e. list(map(func, *iterables)). The number of arguments to func must be the number of iterables listed. Let's see how these rules play out with the following examples.
Traditional Code:
persons = ['alfred', 'tabitha', 'william', 'arla']
uppered_persons = []
for person in persons:
persons_ = person.upper()
uppered_persons.append(persons_)
print(uppered_persons)
Using the map()
function:
persons = ['alfred', 'tabitha', 'william', 'arla']
uppered_persons = list(map(str.upper, persons))
print(uppered_persons)
An Example utilizing the round()
and range()
functions:
circle_areas = [6.56773, 9.57668, 4.00914, 56.24241, 9.01344, 32.00013]
result = list(map(round, circle_areas, range(1,7)))
print(result)
An Example utilizing the zip()
function
my_chars = ['a', 'b', 'c', 'd', 'e']
my_nums = [1,2,3,4,5]
result = list(zip(my_chars, my_nums))
print(result)
Filter
While map()
passes each element in the iterable through a function and returns the result of all elements having passed through the function, filter()
, first of all, requires the function to return boolean values (true or false) and then passes each element in the iterable through the function, "filtering" away those that are false. It has the following syntax:
filter(func, iterable)
The following points are to be noted regarding filter():
- Unlike
map()
, only one iterable is required. - The func argument is required to return a boolean type. If it doesn't, filter simply returns the iterable passed to it. Also, as only one iterable is required, it's implicit that func must only take one argument.
- filter passes each element in the iterable through func and returns only the ones that evaluate to true.
Example:
scores = [66, 90, 68, 59, 76, 60, 88, 74, 81, 65, 92, 85]
def is_A_student(score):
return score > 80
passing = list(filter(is_A_student, scores))
print(passing)
Example:
myStrings = ("demigod", "rewire", "madam", "fortran", "python", "xamarin", "salas", "PHP")
palindromes = list(filter(lambda word: word == word[::-1], myStrings))
print(palindromes)
Reduce
reduce
applies a function of two arguments cumulatively to the elements of an iterable, optionally starting with an initial argument. It has the following syntax:
reduce(func, iterable[, initial])
Where func is the function on which each element in the iterable gets cumulatively applied to, and initial is the optional value that gets placed before the elements of the iterable in the calculation, and serves as a default when the iterable is empty. The following should be noted about reduce():
- func requires two arguments, the first of which is the first element in iterable (if initial is not supplied) and the second element in iterable. If initial is supplied, then it becomes the first argument to func and the first element in iterable becomes the second element.
Example:
from functools import reduce
myNumbers = [3, 4, 6, 9, 34, 12]
def custom_sum(first, second):
return first + second
result = reduce(custom_sum, myNumbers)
print(result)
Example using initial:
from functools import reduce
myNumbers = [3, 4, 6, 9, 34, 12]
def custom_sum(first, second):
return first + second
result = reduce(custom_sum, myNumbers, 10)
print(result)
Exercise
Use each of map
, filter
, and reduce
to fix the broken code.
from functools import reduce
# Use map to print the square of each numbers rounded
# to three decimal places
my_floats = [4.35, 6.09, 3.25, 9.77, 2.16, 8.88, 4.59]
# Use filter to print only the names that are less than
# or equal to seven letters
my_names = ["olumide", "akinremi", "josiah", "temidayo", "omoseun"]
# Use reduce to print the product of these numbers
my_numbers = [4, 6, 9, 23, 5]
# Fix all three respectively.
map_result = list(map(lambda x: x, my_floats))
filter_result = list(filter(lambda name: name, my_names, my_names))
reduce_result = reduce(lambda num1, num2: num1 * num2, my_numbers, 0)
print(map_result)
print(filter_result)
print(reduce_result)
from functools import reduce
my_floats = [4.35, 6.09, 3.25, 9.77, 2.16, 8.88, 4.59]
my_names = ["Jeff", "Alex", "Jonathan", "Richelle", "Anna"]
my_numbers = [4, 6, 8, 10, 2]
map_result = list(map(lambda x: round(x ** 2, 3), my_floats))
filter_result = list(filter(lambda name: len(name) <= 7, my_names))
reduce_result = reduce(lambda num1, num2: num1 * num2, my_numbers)
print(map_result)
print(filter_result)
print(reduce_result)
test_output_contains("[18.922, 37.088, 10.562, 95.453, 4.666, 78.854, 21.068]")
test_output_contains("['Jeff', 'Alex', 'Anna']")
test_output_contains("3840")
success_msg("Excellent!")