====== 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.