====== List Comprehensions ======
[[https://en.wikipedia.org/wiki/List_comprehension|List comprehensions]] are used for creating lists from existing lists and other iterable structures. List comprehensions typically follow formatting similar to [[https://en.wikipedia.org/wiki/Set-builder_notation|set-builder notation]] in discrete mathematics.
===== Syntax =====
Consider the following illustrative Python3 example for generating a list of squares:
>>> sq = []
>>> for i in range(10):
... sq.append(i**2)
...
>>> sq
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
The same could be achieved in the following list comprehension((Note that the list comprehension can also be constructed by considering the set-builder construction for the same example:\\ {//n//2 | //n// ∈ **Z** ∧ 0 ≤ //n// ≤ 9 }.\\ While a full understanding of set-builder notation is not necessary for working with list comprehensions, in some instances they may lead to a more natural translation to list comprehensions than equivalent loop-based code.))
>>> [i**2 for i in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
===== Example Functionality =====
==== Multiple Loops ====
>>> [(x**2, y**2) for x in range(3) for y in range(3)]
[(0, 0), (0, 1), (0, 4), (1, 0), (1, 1), (1, 4), (4, 0), (4, 1), (4, 4)]
====Conditionals====
>>> [(x, y) for x in [1,2,3] for y in [3,1,4] if x != y]
[(1,3), (1,4), (2,3), (2,1), (2,4), (3,1), (3,4)]
====Repetitions====
>>> [i for i in range(1, 5) for j in range(i)]
[1, 2, 2, 3, 3, 3, 4, 4, 4, 4]
====Processing non-range() iterables====
>>> vec = [-4, -2, 0, 2, 4]
>>> [abs(x) for x in vec]
[4, 2, 0, 2, 4]
====Creating a double list====
>>> n = 3
>>> [[i for i in range(j*n, j*n+n)] for j in range(n)]
[[0, 1, 2], [3, 4, 5], [6, 7, 8]]
====Flattening a double list====
>>> vec = [[1,2,3], [4,5,6], [7,8,9]]
>>> [num for elem in vec for num in elem]
[1, 2, 3, 4, 5, 6, 7, 8, 9]
==== Benchmarks ====
List comprehensions are typically faster than their loop-based counterparts, often without fine-tuning. The below tests are taken directly from the above examples.
n = int(10000)
squares = [([(x**2, y**2) for x in range(n) for y in range(n)])]
n = int(argv[1])
squares = []
for i in range(n):
for j in range(n):
squares.append((i**2, j**2))
^ %%n%% ^ square_comprehension.py((Python 3.5.2)) ^ square_loop.py ^
^ 500 | .1864s | .2152s |
^ 1000 | .7104s | .8147s |
^ 1500 | 1.572s | 1.8304s |
^ 2000 | 2.7992 | 3.28s |
Note that both of the above examples require storage of (potentially) millions of tuples. Many problems will not necessarily require //storage// of this many values in memory, but instead iterating over them. In such an instances iteration using for loops or [[python3:generators|Generators]] may be advisable.