
List is a built-in data structure in Python and a collection of data points in square brackets. Lists can be used to store any data type or a mixture of different data types.
In this post, we will cover list comprehensions in python with 11 examples. I tried to order the examples according to their complexity levels (in my opinion).
List comprehension is basically creating lists based on existing iterables. It can also be described as representing for and if loops with a simpler and more appealing syntax. List comprehensions are relatively faster than for loops.

So we iterate over an iterable and do something (optional!) with the items and then put them in a list. In some cases, we just take the items that fit a specified condition.
Let’s start with the examples.
#example 1
import numpy as np
a = [4,6,7,3,2]
b = [x for x in a if x > 5]
b
[6, 7]
We iterate over a list (iterable) and take the elements that are greater than 5 (condition).
The equivalent for loop is:
b = []
for x in a:
if x > 5:
b.append(x)
b
[6, 7]
We can also do something with items before putting them in a new list:
#example 2
import numpy as np
a = [4,6,7,3,2]
b = [x*2 for x in a if x > 5]
b
[12, 14]
We multiply the items that fit the condition by 2 and then put in a list.
The third example is a list of strings:
#example 3
names = ['Ch','Dh','Eh','cb','Tb','Td']
new_names = [name for name in names if name.lower().startswith('c')]
new_names
['Ch', 'cb']
The condition is that string starts with the letter "c". Since we have both capital and lowercase letters, we convert all letters to lowercase first.
The iterable does not have to be a list. It can be any python iterable. For instance, we can iterate over a 2-dimensional NumPy array which is actually a matrix.
#example 4
import numpy as np
A = np.random.randint(10, size=(4,4))
A
array([[1, 7, 4, 4],
[5, 0, 0, 6],
[7, 5, 8, 4],
[1, 3, 2, 2]])
max_element = [max(i) for i in A]
max_element
[7, 6, 8, 3]
We iterate over the rows in matrix A and take the maximum number.
Lists can store any data type. Let’s do an example with a list of lists.
#example 5
vals = [[1,2,3],[4,5,2],[3,2,6]]
vals_max = [max(x) for x in vals]
vals_max
[3, 5, 6]
We create a list of the maximum values in each list.
We can have multiple conditions in a list comprehension.
#example 6
names = ['Ch','Dh','Eh','cb','Tb','Td','Chb','Tdb']
new_names = [name for name in names if
name.lower().endswith('b') and len(name) > 2]
new_names
['Chb', 'Tdb']
We get the strings that end with the letter "b" and have a length greater than 2.
We can combine multiple conditions with other logical operators:
#example 7
names = ['chb', 'ydb', 'thd', 'hgh']
new_names = [name for name in names
if name.endswith('b') | name.startswith('c')]
new_names
['chb', 'ydb']
We can also have nested list comprehensions which are a little bit more complex. They represent nested for loops.
Consider the following list of lists:
vals = [[1,2,3],[4,5,2],[3,2,6]]
We want to take out each element from the nested lists so the desired output is:
vals = [1,2,3,4,5,2,3,2,6]
Here is the nested list comprehension that does this operation:
#example 8
vals = [[1,2,3],[4,5,2],[3,2,6]]
vals_exp = [y for x in vals for y in x]
vals_exp
[1, 2, 3, 4, 5, 2, 3, 2, 6]
The syntax may not seem very intuitive. It will be clear when compared with the equivalent for loop.

We put the blocks of a nested for loop into a list comprehension.
Note: There is a much easier way to do the operation in example 7 which is the explode function of pandas. I used list comprehension just to show the structure. It can be done with the explode function as follows:
pd.Series(vals).explode()
It returns a pandas series but you can easily convert it to a list.
We can also add conditions in nested list comprehensions. Consider the following list of lists with strings.
text = [['bar','foo','fooba'],['Rome','Madrid','Houston'], ['aa','bb','cc','dd']]
We only want the strings in nested lists whose length is greater than 3.
#example 9
text_1 = [y for x in text if len(x)>3 for y in x]
text_1
['aa', 'bb', 'cc', 'dd']
We put the condition on the nested lists, not on individual elements. Thus, the equivalent nested for/if loop syntax is as follows.

We can also put a condition on individual elements.
#example 10
text_2 = [y for x in text for y in x if len(y)>4]
text_2
['fooba', 'Madrid', 'Houston']
We now have strings that are longer than 4 characters. Since the condition is on individual elements, the equivalent nested for/if loops:

We may also need to put conditions on both nested lists and individual items.
#example 11
text_3 = [y.upper() for x in text if len(x) == 3 for y in x if y.startswith('f')]
text_3
['FOO', 'FOOBA']
We get the items that start with the letter "f" in nested lists with a length of 3 and then convert all the letters of selected items to uppercase.
The equivalent for/if loops:

Tip: When you are not sure and cannot find out the syntax for list comprehension, try to build it with for/if loops. Then you can convert it to a list comprehension by adding individual blocks of loops into the list comprehension.
Bonus: When not to use list comprehension
List comprehension loads the entire output list into memory. This is acceptable or even desirable for small or medium-sized lists because it makes the operation faster. However, when we are working with large lists (e.g. 1 billion elements), list comprehension should be avoided. It may cause your computer to crash due to the extreme amount of memory requirement.
A better alternative for such large lists is using a generator that does not actually create a large data structure in memory. A generator creates items when they are used. After the items are used, the generator throws them away. Using a generator, we can ask for the next item in an iterable until we reach the end and store a single value at a time.
Thank you for reading. Please let me know if you have any feedback.