8 explained examples of list comprehension in Python

What is list comprehension

List comprehension is a concise way used instead of for-loop when you want to create a new list based on another iterable (list, tuple, dictionary, set, string, generator, ...).

You get to do this:

[do_this(element) for element in thislist if thisistrue]

instead of this:

my_list = []
for element in thislist:
    if thisistrue:
        my_list.append(do_this(element))

It's easily recognizable and more readable than (at least) 3-lines long for-loop. It's usually faster and helps you maintain your code clean and simple. It's especially neater when you want to find the common elements from two lists. You'd need two for loops for that and still only one "not-that-complicated" line for list comprehension.

list_comprehension_explained.png

The result of a list comprehension is always a new list, that's why the expression is in square brackets (there is also a dictionary comprehension, where the result is a dictionary and set comprehension where the result is a dictionary/set accordingly).

There are three parts of the comprehension inside the brackets:

  • what to do (e.g. add 2 to each element)
  • for what in which list (e.g. for element in the list of numbers)
  • when (e.g. when the element is dividable by two)

The third part, if, can be omitted. In that case, the expression will be performed on each element of the old list and the length of the new and old list will be the same.

A very simple showcase of a list comprehension would be this:

[x+2 for x in [2, 3, 4]]

# result: [4, 5, 6]

You add 2 to each item in the list ([2+2, 3+2, 4+2]) because there is no condition.

But let's say we want the addition to be performed only on even numbers:

[x+2 for x in [2, 3, 4] if x % 2 == 0]

# result: [4, 6]

Now the addition is performed only on 2 and 4 ([2+2, 4+2]). 3 is not an even number, so it is omitted from the creation of a new list.

Those are two very simple cases, just enough for you to get an idea. In the real world, you probably won't need to add a number to a list of numbers. List comprehension in the real world is often used to perform some kind of filtering.

Filtering

When you want to create a new list with just some of the elements from the old list, you set a condition with if that will let only some of the elements pass. You can either do something with the elements that match the condition (new_x = x+2) or not (new_x = x).

Simple filtering

You know those "The hottest day this summer" news titles? Let's say you have the list of the daily temperatures from the summer and you want to get only the temperature higher than 30°C. This is how you do it:

all_temperatures = [28, 23, 38, 32, 28, 31, 29, 33]

highest_temperatures = [temperature for temperature in all_temperatures if temperature > 30]

# result: [38, 32, 31, 33]

In this case, you didn't change the elements. You just took the numbers higher than 30 from the all_temperatures list and put them into the highest_temperatures list. The all_temperatures list is unchanged.

simple_filter.png

Filtering based on the length of the element

You got a list of messages from your users. The field was required, so some of them just wrote few random letters to skip it. You want to filter out the ones with some values - the string has to be at least 10 characters long:

messages = ['Praesent orci nulla, pellentesque a consectetur id.', '/', 'zblj', 'Aliquam pellentesque diam et nibh hendrerit semper. ', 'test']
valuable_messages = [message for message in messages if len(message) > 10]

# result: ['Praesent orci nulla, pellentesque a consectetur id.', 'Aliquam pellentesque diam et nibh hendrerit semper. ']

As in the previous case, you didn't do anything with the element on the list. You just checked if it's long enough and if it is, you added it to the new list.

Filtering based on part of the tuple

Let's say you have a tuple of tuples with a name and a grade a student got for the test. Some of the students were sick, so they weren't graded and now you want to know which of the students you need to prepare another test.

grades = (('Anna', 'B'), ('May', 'A'), ('Tina', ''), ('Claire', ''), ('Beth', 'A'))

ungraded = [name for name, grade in grades if not grade]

# result: ['Tina', 'Claire']

As you can see, this is not a list, but a tuple of tuples. In the list comprehension, you declared that the first part of the inside tuple is called name and the second one is called grade (this is called tuple unpacking). Those names are of your choosing and matter only for readability purposes. For Python's sake, they could be called zblj and gn. You take the name from each tuple in the outer tuple and put it in the new list (there won't be grades listed in the new list, just names). But the element (name) goes to the new list only if the second part of the tuple (grade) is an empty string.

list_tuple.png

This is the only case we didn't create a list out of the list but out of a tuple. It doesn't matter what the source object is, only that is iterable. The outcome, however, is always a list.

Filtering and changing the element

If you need to extract numbers from the list of strings, you can check if the string contains only digits and if it does, you can convert it to an integer.

alphanumeric = ["47", "abcd", "21st", "n0w4y", "test", "55123"]
numbers = [int(string) for string in alphanumeric if string.isdigit()]

# result: [47, 55123]

On the new list are the elements from the old list that contained only digits and were transformed to integers.

Working with more than one list

Another possibility where list comprehension can be useful is when you need to somehow combine two or more lists.

Combining all the elements

You want to order mobile phones for your store. Your boss told you which color and which models to order. To make it easy for yourself, you can combine all the selected colors with all the selected models:

colors = ["red", "blue", "black"]
models = ["12", "12 mini", "12 Pro"]

order = [(model, color) for model in models for color in colors]

# result: [('12', 'red'), ('12', 'blue'), ('12', 'black'), ('12 mini', 'red'), ('12 mini', 'blue'), ('12 mini', 'black'), ('12 Pro', 'red'), ('12 Pro', 'blue'), ('12 Pro', 'black')]

tuple_from_two_lists.png

Here you combined every item from the first list with every item on the second list. The length of the new list will be the product of both lengths (len(list_1) * len(list_2))

Common elements

Here's one for the Disney fans. You have a list of all the characters from Frozen. And you have a list of all the Disney princesses. Now you would like to know which Disney princesses are in the Frozen movie.

frozen = ["Anna", "Elsa", "Sven", "Olaf"]
princesses = ["Rapunzel", "Elsa", "Anna", "Ariel"]

princesses_from_frozen = [frozen_char for frozen_char in frozen for princess in princesses if frozen_char == princess]

In this case, you go through all the elements in the first list and you compare every single element with all the elements from the second list. The new list contains only the elements that appeared on both lists.

This might be the easiest to explain if you see how this would look with a for-loop:

princesses_from_frozen = []
for frozen_char in frozen: # loop through the first list
    for princess in princesses: # loop through the second list
        if frozen_char == princess: # compare the element from the first loop with the element from the second one
            princesses_from_frozen.append(frozen_char)

If you didn't previously, now you probably get the beauty of list comprehension?

Combining elements with the same position

names = ["John", "Mary", "Lea"]
surnames = ["Smith", "Wonder", "Singer"]
ages = ["22", "19", "25"]

combined = [F"{name} {surname} - {age}" for name, surname, age in zip(names, surnames, ages)]

# result: ['John Smith - 22', 'Mary Wonder - 19', 'Lea Singer - 25']

Here we need to use the Python zip function.

zip function returns a zip object, which is an iterator of tuples where the elements on the same position from different lists are paired together.

So, zip(names, surnames) would need to be turned to something readable with tuple():

print(tuple(zip(names, surnames)))

and would return:

(('John', 'Smith'), ('Mary', 'Wonder'), ('Lea', 'Singer')).

After we created a zip object, we assigned names for each element in the tuple - name, surname, age and combined all three in a string for each tuple (F"{name} {surname} - {age}"). If the lists are of different lengths, the zip will work with the shortest list. So the length of the new list will be the same as the length of the shortest list.

Using it with function

If you need to do quite a lot with the elements, you can use a function in the expression and do the logic in the function. That way, your list comprehension stays short and readable.

Convert euros to dollars

def convert_to_dol(eur):
    return round(eur * 1.19, 2)


prices = [22.30, 12.00, 0.99, 1.10]
dollar_prices = [convert_to_dol(price) for price in prices]

#result: [26.54, 14.28, 1.18, 1.31]

The above example would also work written like this:

dollar_prices = [round(price * 1.19, 2) for price in prices]

but it's not as readable, right?

Conclusion

List comprehension can be confusing at first, but it's really worth learning. You might have to do few more cases, but after a while, it will be easier to make sense of a list comprehension than of a for loop, I promise. However, don't go switching all of your for-loops with a list comprehension. It is only to be used when you need to create a new list from some other list(s).

If you're looking for some practice, here are a few ideas:

  • Add a list of possible memory sizes to Combining all the elements example and create tuples combined from all three lists.
  • Take the code from Common elements example, add a new list - princesses_i_like, and try to find the name that appears on all three lists (you can put in any names you want but if you want to get a result, you have to include Anna or Elsa).
  • Take the code from Combining elements with the same position example and combine the data only for people older than 20.

You can find the solutions in the comments. If you think of another good use case for list comprehension, feel free to post it in the comments.

Image by Alexandra_Koch from Pixabay

GirlThatLovesToCode's photo

The solutions for the practice ideas:

[(model, color, size) for model in models for color in colors for size in sizes]

princesses_from_frozen = [frozen_char for frozen_char in frozen for princess in princesses for i_like in princesses_i_like if frozen_char == princess and frozen_char == i_like]

[F"{name} {surname} - {age}" for name, surname, age in zip(names, surnames, ages) if int(age) > 20]

Jan Giacomelli's photo

Great post

Vince's photo

This is a great resource, thank you for writing it. I'll be adding it to my list of extra reading for my class.

GirlThatLovesToCode's photo

This is a comment every author wants to see (:

Amal Shaji's photo

Super cool post. List comprehensions are very useful. I've got some alternate solutions to make life harder.

Simple Filtering

image.png

Filtering and applying some operation

image.png

Combining all elements

image.png

Common elements

image.png

Using it with a function

Use map(Callable, Iterable)

image.png

GirlThatLovesToCode's photo

Thanks for making life harder :P

Tosin Ayodele's photo

Exactly my point when I went through the work GirlThatLovesToCode

Mohammed Sameeruddin's photo

Nice write up. 😀

Don't you think, the heading "Convert dollars to euros" should actually be "Convert euros to dollars".

Moreover the function name is also convert_to_dol().

GirlThatLovesToCode's photo

Thank you for noticing, I fixed it.

Kah's photo

Nice list. I once used comprehension to divide a list into smaller groups. For example:

>>> source = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]                                    
>>> [source[i:min(i + group_size, len(source))] for i in range(0, len(source), group_size)]
[[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13]]
GirlThatLovesToCode's photo

Great idea, thanks for sharing (:

Brian Ketelboeter's photo

A nice skill to discuss. Excellent choice of article content and clear explanation

GirlThatLovesToCode's photo

Thank you, I'm glad you liked it.

Siddharth Chandra's photo

Totally agree with you on that list comprehensions work faster than traditional loops. Generally, if we write more pythonic code, it will always be more time-efficient I think.

Show +1 replies
Siddharth Chandra's photo

Yeah, I feel like as the complexity increases, python code execution tends to be slower irrespective of its pythonic nature 😅

GirlThatLovesToCode's photo

This is an interesting idea 😅

Brian Ketelboeter's photo

it is a small thing, but you sometimes use 'array' (non-python) when you mean 'list' (python). Again, very small.

GirlThatLovesToCode's photo

Thank you for pointing that out, I fixed it.