Search notes:

Python: List comprehension

result = [ expr(x) for x in someList ]
result = [ expr(x) for x in someList if criterion(x)]
A list comprehension is a construct to evaluate an expression on each element of a list (or more generally in a sequence). The list comprehension returns another list that consists of the values of the expressions.
Additionally, it can be augmented with a condition (using the if keyword) in which case only elements are returned where the condition evaluates to true.

Calculating squares of a list

This is demonstrated with the following simple example. The expression that is caluclated is i**2 which is evaluated for each i in the given list (which consists 2, 4, 5 and 7).
squares = [i**2 for i in [2,4,5,7] ]
print(squares)
#
# [4, 16, 25, 49]
Github repository about-python, path: /types/list/comprehension/squares.py
Compare with map(lambda i: i**2, [2,4,5,7])

Using a condition

The following example calculates the square roots of numbers with math.sqrt. Since math.sqrt throws a ValueError for negative numbers, the optional if clause of the list comprehension is used to only calculate square roots for x >= 0.
import math

print ( [ math.sqrt(x) for x in [4,-16,25,64,-28] if x >= 0 ] )
#
# [2.0, 5.0, 8.0]
Github repository about-python, path: /types/list/comprehension/criterion.py

Serially connecting list comprehensions

List comprehensions can be used serially where the result (that is: the created list) of the left list comprehension is the expression that feeds into the right list comprehension.
This technique is demonstrated in the following example:
numbers = [ [ 'one' , 'two' , 'three'],
            [ 'eins', 'zwei', 'drei' ],
            [ 'un'  , 'dos' , 'tres' ]
          ]

flat_list = [
        translation                       # <-- 3: evaluate translation, create list
             for language    in numbers   # <-- 1: iterate over each element in numbers, assign to language
             for translation in language  # <-- 2: iterate over each element in each language, assign to translation
      ]

print(flat_list)
#
#  ['one', 'two', 'three', 'eins', 'zwei', 'drei', 'un', 'dos', 'tres']
Github repository about-python, path: /types/list/comprehension/for-in-for-in.py

Transposing a list of lists

numbers = [ [ 'one' , 'two' , 'three'],
            [ 'eins', 'zwei', 'drei' ],
            [ 'un'  , 'dos' , 'tres' ]
          ]

transposed = [
    [ translation[number] for translation in numbers            ]
                          for number      in range(len(numbers))
]

print(transposed)
#
#  [['one', 'eins', 'un'], ['two', 'zwei', 'dos'], ['three', 'drei', 'tres']]
Github repository about-python, path: /types/list/comprehension/transpose.py
Compare with transposing a matrix with zip.

Creating multidimensional lists

Serially connecting list comprehension allows to create multi-dimensional lists, as is shown in the following example: it creates a list that consists of three lists, which in turn consist of four numbers:
grid = [
         [ x * y for x in range(1, 5)]  # <- Create a list with 4 elements, y is determined by the following list comprehension
                 for y in range(0, 3)   # <- Create 3 of the previous expression (which is a list of 4 elements)
       ]

print(grid)
#
#  [[0, 0, 0, 0], [1, 2, 3, 4], [2, 4, 6, 8]]
Github repository about-python, path: /types/list/comprehension/2D.py

Creating lists with lists with increasing number of elements

By connecting list comprehensions, it is also possible to create a list whose elements are lists with an increasing number of elements:
a = [ [R  for L in range(0,R) ]
          for R in range(1,6) ]

print(a)
#
#  [[1], [2, 2], [3, 3, 3], [4, 4, 4, 4], [5, 5, 5, 5, 5]]

b = [ [L  for L in range(1,R) ]
          for R in range(2,7) ]
print(b)
#
#  [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [1, 2, 3, 4, 5]]
Github repository about-python, path: /types/list/comprehension/increasing-number-of-elements.py

SyntaxError: iterable unpacking cannot be used in comprehension

Here's a list:
L = [
   ('one.eins.uno',  1),
   ('foo.bar.baz' , 42),
   ('x.y.z'       , 99)
]
I want to produce a list from L where each element is a tuple that consists of the elements of the text and the number.
The following statement throws SyntaxError: iterable unpacking cannot be used in comprehension:
[ *(e[0].split('.'), e[1])  for e in L ]
This works as intended:
[(*txt.split('.'), num) for txt, num in L]
The statement produces:
[('one', 'eins', 'uno', 1), ('foo', 'bar', 'baz', 42), ('x', 'y', 'z', 99)]

See also

Dict comprehension
The built-in functions map() and filter().
Passing function arguments whose values are created by a list comprehension
List comprehesion is also understood in DuckDB.

Index