Python Topics : Flatten a List of Lists
How to Flatten a List of Lists With a for Loop
steps using a for loop
  1. create a new empty list to store the flattened data
  2. iterate over each nested list or sublist in the original list
  3. add every item from the current sublist to the list of flattened data
  4. return the resulting list with the flattened data
the list of lists to be flattened
matrix = [
    [9, 3, 8, 3],
    [4, 5, 2, 8],
    [6, 4, 3, 1],
    [1, 0, 4, 5],
]
recursive function to flatten a list of lists
def flatten_extend(matrix):
    flat_list = []
    for row in matrix:
        flat_list.extend(row)
    return flat_list
flat_list.extend(row) is the same as flat_list += row

Using a Comprehension to Flatten a List of Lists
core syntax of a list comprehension
[expression(item) for item in iterable]
components
  1. expression() is a Python expression that returns a concrete value
    most of the time that value depends on item
  2. item is the current object from iterable
  3. iterable can be any Python iterable object
use a list comprehension to flatten matrix
def flatten_comprehension(matrix):
    return [item for row in matrix for item in row]
two nested for clauses
  • for each rows in matrix
  • for each item in each row
Flattening a List Using Standard-Library and Built-in Tools

can use any of these tools
  • the chain() function from the itertools module
  • the reduce() function from the functools module
  • the built-in sum() function
Chaining Iterables With itertools.chain()
the chain() function chains multiple iterables into a single one
instead of returning a list, chain() returns an iterator which yields items from all the input iterables until they get exhausted
can take advantage of chain() along with list() to flatten a list of lists
>>>from itertools import chain

>>>def flatten_chain(matrix):
...     return list(chain.from_iterable(matrix))
...

>>>matrix = [
...     [9, 3, 8, 3],
...     [4, 5, 2, 8],
...     [6, 4, 3, 1],
...     [1, 0, 4, 5],
... ]

>>>flatten_chain(matrix)
[9, 3, 8, 3, 4, 5, 2, 8, 6, 4, 3, 1, 1, 0, 4, 5]
chain is implemented as a class
.from_iterable() is a class method
method provides an alternative constructor
can use alternative c'tor to build a chain from an iterable of iterables
builds a list out of the iterator that .from_iterable() returns

Concatenating Lists With functools.reduce()
the reduce() function from the functools module is another tool which can be used to flatten lists of lists
reduce() takes a pair of items and computes a partial result
then it uses that result and the next item to compute the next partial result
process creates an implicit accumulator that stores the cumulative value in every step

can use different function-like objects with reduce() to flatten a list of lists
below uses a custom lambda function

>>> from functools import reduce

>>> def flatten_reduce_lambda(matrix):
...     return list(reduce(lambda x, y: x + y, matrix, []))
...

>>> matrix = [
...     [9, 3, 8, 3],
...     [4, 5, 2, 8],
...     [6, 4, 3, 1],
...     [1, 0, 4, 5],
... ]

>>> flatten_reduce_lambda(matrix)
[9, 3, 8, 3, 4, 5, 2, 8, 6, 4, 3, 1, 1, 0, 4, 5]
reduce arguments
  • the first argument to reduce() is the lambda function
    takes two arguments, x and y, and returns their sum
  • matrix is passed as the second argument
  • an empty list as the third argument
    argument holds an initial value to start the computation with.
can also use other functions from the standard library
can use the following functions from the operator module
  • add() sums two numbers together
    equivalent to the addition operator (+)
  • concat() concatenates two values together
    equivalent to the concatenation operator on lists (+)
  • iconcat() concatenates two values together in place
    equivalent to the augmented concatenation operator (+=)
Using sum() to Concatenate Lists
use sum() to concatenate the sublists in matrix
>>> def flatten_sum(matrix):
...     return sum(matrix, [])
...

>>> matrix = [
...     [9, 3, 8, 3],
...     [4, 5, 2, 8],
...     [6, 4, 3, 1],
...     [1, 0, 4, 5],
... ]

>>> flatten_sum(matrix)
[9, 3, 8, 3, 4, 5, 2, 8, 6, 4, 3, 1, 1, 0, 4, 5]
Considering Performance While Flattening Lists
a small script to test how quickly the different approaches can flatten lists of lists
from functools import reduce
from itertools import chain
from operator import add, concat, iconcat

def flatten_extend(matrix):
    flat_list = []
    for row in matrix:
        flat_list.extend(row)
    return flat_list

def flatten_concatenation(matrix):
    flat_list = []
    for row in matrix:
        flat_list += row
    return flat_list

def flatten_comprehension(matrix):
    return [item for row in matrix for item in row]

def flatten_chain(matrix):
    return list(chain.from_iterable(matrix))

def flatten_reduce_lambda(matrix):
    return list(reduce(lambda x, y: x + y, matrix, []))

def flatten_reduce_add(matrix):
    return reduce(add, matrix, [])

def flatten_reduce_concat(matrix):
    return reduce(concat, matrix, [])

def flatten_reduce_iconcat(matrix):
    return reduce(iconcat, matrix, [])

def flatten_sum(matrix):
    return sum(matrix, [])
performance.py
from timeit import timeit

import flatten

SIZE = 1000
TO_MS = 1000
NUM = 10
FUNCTIONS = [
    "flatten_extend",
    "flatten_concatenation",
    "flatten_comprehension",
    "flatten_chain",
    "flatten_reduce_lambda",
    "flatten_reduce_add",
    "flatten_reduce_concat",
    "flatten_reduce_iconcat",
    "flatten_sum",
]

matrix = [list(range(SIZE))] * SIZE

results = {
    func: timeit(f"flatten.{func}(matrix)", globals=globals(), number=NUM)
    for func in FUNCTIONS
}

print(f"Time to flatten a {SIZE}x{SIZE} matrix (in milliseconds):\n")

for func, time in sorted(results.items(), key=lambda result: result[1]):
    print(f"{func + '()':.<30}{time * TO_MS / NUM:.>7.2f} ms")
output
$ python performance.py
Time to flatten a 1000x1000 matrix (in milliseconds):

flatten_concatenation()..........1.95 ms
flatten_extend().................2.03 ms
flatten_reduce_iconcat().........2.68 ms
flatten_chain()..................4.60 ms
flatten_comprehension()..........7.79 ms
flatten_sum().................1113.22 ms
flatten_reduce_concat().......1117.15 ms
flatten_reduce_lambda().......1117.52 ms
flatten_reduce_add()..........1118.80 ms
Flattening Python Lists for Data Science With NumPy
flattening a numpy array of arrays (Python list of lists)
>>> import numpy as np

>>> matrix = np.array(
...     [
...         [9, 3, 8, 3],
...         [4, 5, 2, 8],
...         [6, 4, 3, 1],
...         [1, 0, 4, 5],
...     ]
... )

>>> matrix
array([[9, 3, 8, 3],
       [4, 5, 2, 8],
       [6, 4, 3, 1],
       [1, 0, 4, 5]])

>>> matrix.flatten()
array([9, 3, 8, 3, 4, 5, 2, 8, 6, 4, 3, 1, 1, 0, 4, 5])
index