How To Replace Your Python For Loops with Map, Filter, and Reduce

Write more semantic code with functional programming

Do you ever look at your code and see a waterfall of for loops? Do you find yourself having to squint your eyes and lean towards your monitor to get a closer look?

I know I do.

For loops are a Swiss army knife for problem-solving, but, when it comes to scanning code to get a quick read of what you’ve done, they can be overwhelming.

Three techniques — map, filter, and reduce — help remedy the for loop mania by offering functional alternatives that describe why you’re iterating. I previously wrote about getting started with these techniques in JavaScript, but the implementation is slightly different in Python.

We’ll briefly introduce each of the three techniques, highlight the syntactic differences between them in JavaScript and Python, and then give examples of how to convert common for loops.

What are Map, Filter, and Reduce?

Reviewing my previously written code, I realized that 95% of the time when looping through strings or arrays I do one of the following: map a sequence of statements to each value, filter values that meet specific criteria, or reduce the data set to a single aggregate value.

With that insight, these three methods are recognition — and implementation — that the reason you loop through an iterable often falls into one of these three functional categories:

  • Map: Apply the same set of steps to each item, storing the result.
  • Filter: Apply validation criteria, storing items that evaluate True.
  • Reduce: Return a value that is passed from element to element.

What Makes Python Map/Filter/Reduce Different?

In Python, the three techniques exist as functions, rather than methods of the Array or String class. This means that instead of writing you would write map(function, my_list).

Additionally, each technique will require a function to be passed, which will be executed for each item. Often, the function is written as an anonymous function (called a fat arrow function in JavaScript). However, in Python you often see lambda expressions being used.

The syntax between a lambda expression and arrow function is actually quite similar. Swap the => for a : and make sure to use the keyword lambda and the rest is almost identical.

// JavaScript Arrow Function
const square = number => number * number;// Python Lambda Expression
square = lambda number: number * number

One key difference between arrow functions and lambda expressions is that arrow functions are able to expand into full-blown functions with multiple statements while lambda expressions are limited to a single expression that is returned. Thus, when using map()filter(), or reduce() if you need to perform multiple operations on each item, define your function first then include it.

def inefficientSquare(number):
   result = number * number
   return resultmap(inefficientSquare, my_list)

Replacing For Loops

All right, on to the good stuff. Here are three examples of common for loops that will be replaced by map, filter, and reduce. Our programming prompt: Calculate the sum of the squared odd numbers in a list.

First, the example with basic for loops. Note: This is purely for demonstration and could be improved even without map/filter/reduce.

numbers = [1,2,3,4,5,6]
odd_numbers = []
squared_odd_numbers = []
total = 0# filter for odd numbers
for number in numbers:
   if number % 2 == 1:
      odd_numbers.append(number)# square all odd numbers
for number in odd_numbers:
   squared_odd_numbers.append(number * number)# calculate total
for number in squared_odd_numbers:
   total += number# calculate average

Let’s convert each step to one of the functions:

from functools import reducenumbers = [1,2,3,4,5,6]odd_numbers = filter(lambda n: n % 2 == 1, numbers)squared_odd_numbers = map(lambda n: n * n, odd_numbers)total = reduce(lambda acc, n: acc + n, squared_odd_numbers)

There are a few important points of syntax to highlight.

  • map() and filter() are natively available. However, reduce() must be imported from the functools library in Python 3+.
  • The lambda expression is the first argument in all three functions while the iterable is the second argument
  • The lambda expression for reduce() requires two arguments: the accumulator (the value that is passed to each element) and the individual element itself.

Source: medium