Looping over selected items

Martin McBride, 2018-03-02
Tags for loop, filter, lambda functions
Categories python language, intermediate python
In section Python language

Suppose you wanted to loop through a list of strings and print all the strings that are more than 3 characters long. You could do it like this:

values = ['a', 'bcd', 'efgh', 'pqrst', 'yz']

def longer_than_3(s):
    return len(s) > 3

for v in values:
    if longer_than_3(v):

The longer_than_3 function returns true if the string is longer than 3 characters, or false otherwise. If it is true, we print the string, and maybe do some other stuff. If it is false, we skip the entire body of the loop.

This code is fine as it is, but we could improve it slightly using the filter function.

Using filter

The filter function accepts a predicate, and a sequence of values. A predicate is a function that accepts a single parameter, and returns a boolean value. For example, our longer_than_3 function is a predicate because it accepts a single paramter (a string) and returns True or False depending on whether the string has more than 3 characters.

filter applies the predicate to each item in the sequence, and returns a new sequence containing only those items for which the predicate returned true.

So how do we use filter in a loop? Well, much the same as reversed or any of the other loop functions, like this:

values = ['a', 'bcd', 'efgh', 'pqrst', 'yz']

def longer_than_3(s):
    return len(s) > 3

for v in filter(longer_than_3, values):

The advantage of using filter

Clearly, our code is now one line shorter. But the real advantage, as ever, is that it makes the intent of the code clearer.

The filter function makes it totally clear that the filtering applies to the whole loop. It brings the filter functionality out of the body of the loop and places it directly in for statement itself.

On the other hand, the if statement (in the original code at the start of the article) is a little more ambiguous. You need to inspect the loop before deciding that the condition affects the entire loop body, rather than just part of it. This isn't too hard with a simple two line loop body, but it is less obvious in complex code.

Using a lambda function

In this case, the function we are using is only a single line of code, so we can use a lambda function instead of a function declaration. This definition creates an unnamed lambda function equivalent to longer_than_3:

lambda x: len(x) > 3

Here is how we use it in the code (notice that the longer_than_3 function is no longer required):

values = ['a', 'bcd', 'efgh', 'pqrst', 'yz']

for v in filter(lambda x: len(x) > 3, values):

In summary, if you are writing a loop that only processes certain elements within the sequence, consider using a filter function in the for loop, rather than an if statement in the body of the loop, to make the intent of the code clear.

If the selection criterion is a simple, one line function, consider using a lambda function for code brevity and readability.

If you found this article useful, you might be interested in the book Functional Programming in Python, or other books, by the same author.


Tag cloud

2d arrays abstract data type alignment and array arrays bezier curve built-in function close closure colour comparison operator comprehension context conversion data types design pattern device space dictionary duck typing efficiency encryption enumerate filter font font style for loop function function composition function plot functools generator gif gradient greyscale higher order function html image processing imagesurface immutable object index inner function input installing iter iterator itertools lambda function len linspace list list comprehension logical operator lru_cache mandelbrot map monad mutability named parameter numeric python numpy object open operator optional parameter or partial application path positional parameter print pure function radial gradient range recipes recursion reduce rgb rotation scaling sequence slice slicing sound spirograph str stream string subpath symmetric encryption template text text metrics transform translation transparency tuple unpacking user space vectorisation webserver website while loop zip

Copyright (c) Axlesoft Ltd 2020