There have been times when I wanted to perform a simple for-loop filter operation on a list, and I’ve often wondered if there’s a quick and simple way to do this without having to import any libraries. What I discovered is that there was an easy way, and what’s awesome about it is that it can be done in one simple line!
If you’ve been operating with dictionaries or lists, you would have likely come across a need to loop through each key or element within those structures to only obtain a certain set of data from it, or to obtain a new modified set of data from the original structure.
For example, recently I wanted to calculate the average of each row in a two-dimensional list , and I thought to myself: Is there an easy way to get the average of each row?
Thankfully, by using a technique known as list comprehensions I can achieve the result intended in a simple and concise manner.
Assume I have the following 2D list of numbers:
data = [[11, 20, 35], [110, 230, 390], [1280, 2870, 3110]]
To create a list of averages for each row of the data grid above, we would create our one-liner for loop (list comprehension) as follows:
average_per_row = [sum(row) / len(row) for row in data] print(average_per_row) # [22.0, 243.33333333333334, 2420.0]
Notice what has happened with our single line of code:
First, we have everything wrapped in the familiar list square brackets annotation, then within those brackets we have our operation on what we want to do with each for-loop iteration .
Next, as I want to perform a simple average calculation on each row, I know that at each iteration of the for-loop will result in each row being returned, and I’ve labelled this returned variable with the appropriate label
. Therefore, at each iteration of the for-loop I’m receiving the following data:
1st iteration = [11, 20, 35] 2nd iteration = [110, 230, 390] 3rd iteration = [1280, 2870, 3110]
At each iteration, I then perform what I need to calculate my simple average for each result:
sum(row) / len(row)
The result from this calculation is then stored as a new element in my new list:
1st iteration = [11, 20, 35] = 66 / 3 = 22 2nd iteration = [110, 230, 390] = 730 / 3 = 243.33333333333334 3rd iteration = [1280, 2870, 3110] = 7260 / 3 = 2420 Result = [22, 243.33333333333334, 2420]
I’m able to achieve my desired result, without needing to write more lines of code. The equivalent of what I did in one line can be seen using multiple lines like this:
average_per_row =  for row in data: average_per_row.append(sum(row) / len(row))
Our single line for-loop took three times as many lines!
Filter Elements For Loop One-Liner
What, though, if I wanted to filter each of the elements in the list before any operations are performed?
Suppose I had a header section in my
variable that contained strings, and I wanted to skip it from my calculations.
Here’s our example with one modification:
data = [['this','is a', 'header'], [11, 20, 35], [110, 230, 390], [1280, 2870, 3110]]
We can still do all this using our one-liner for-loop, but by adding our conditions after the loop statement, like so:
average_per_row = [sum(row) / len(row) for row in data if type(row) is not str]
Notice in this example we’ve extended our one-line for-loop to include the condition:
if type(row) is not str
If the first element in our row’s list is not of type
then this row will not be used to perform our average, when we
this produces the same result as before, as shown here:
[22, 243.33333333333334, 2420]
If Else List Comprehensions
What if I wanted to report something for the row which didn’t return anything?
Is there a way I can use an if-else statement in my list comprehension?
Unfortunately, an if-else clause at the end of the for-loop statement does not work, however, it does work if the if-else clause is placed before the for-loop statement.
You may recall that Python provides a conditional expression (otherwise known as a ternary operator ) which allows for an if-else statement to be placed on one line , like so:
result = x if C else y
By using this same concept, I can insert the ternary operator within my list comprehension like so to be able to filter and provide the result I need for elements within the for-loop that I’d like to completely change:
average_per_row = [sum(row) / len(row) if type(row) is not str else None for row in data]
Notice the ternary operation used inside the list comprehension:
sum(row) / len(row) if type(row) is not str else None
This conditional expression will perform the simple average operation if the type of the first element within each returned list is not of type string, otherwise if it is it will return
Now my result is as follows:
average_per_row = [sum(row) / len(row) if type(row) is not str else None for row in data] print(average_per_row) # [None, 22.0, 243.33333333333334, 2420.0]
To apply a simple filter and obtain a list from your existing data structures is an easy one line piece of code in Python. It enables quicker coding to accomplish a simple task, and doesn’t bloat your screen.
To use a one line list comprehension in Python wrap your expression in square brackets
(the standard list syntax), with inside those brackets inserting your operation (or ternary operator with an if-else statement) followed by the for-loop statement of the data being iterated through.