Joining Sequences in Python
The numerous ways Python offers to concatenate sequences such as lists, strings, byte arrays etc.
Joining sequences of different types
Let’s assume we have the following data:
numbers = [1, 2]
strings = ('three', 'four')
binary = b'\x05\x06'
Our data is stored in three collections of different types (list, tuple
and bytes). Now we want to join numbers
, strings
and binary
together
into a single flat list [1, 2, 'three', 'four', 5, 6]
.
Traditional approach
The most obvious way to do it is arguably a list comprehension:
data = [numbers, strings, binary]
joined = [item for sequence in data for item in sequence]
>>> joined
[1, 2, 'three', 'four', 5, 6]
which is equivalent to a regular nested loop:
joined = []
for sequence in data:
for item in sequence:
joined.append(item)
which in turn can be simplified by using the list.extend
method:
joined = []
for sequence in data:
joined.extend(sequence) # or: joined += sequence
>>> joined
[1, 2, 'three', 'four', 5, 6]
Another interesting technique is a list literal with the *
unpacking notation:
>>> [*numbers, *strings, *binary]
[1, 2, 'three', 'four', 5, 6]
but this one becomes rather impractical if we have many sequences to join.
Functional approach
Alternatively, out iterable sequences can be concatenated using
itertools.chain
:
from itertools import chain
>>> list(chain(*data)) # or: [*chain(*data)]
[1, 2, 'three', 'four', 5, 6]
which is equivalent to
>>> list(chain.from_iterable(data)) # or: [*chain.from_iterable(data)]
[1, 2, 'three', 'four', 5, 6]
Joining sequences of the same type
In addition to all the solutions demonstrated above, sequences of the same type can typically be concatenated by simply summing them together. In the following scenario, we have all our data stored in lists:
numbers = [1, 2]
strings = ['three', 'four']
floats = [5.0, 6.0]
Again, we intend to join the numbers and strings into a single flat list
[1, 2, 'three', 'four', 5.0, 6.0]
. The first solution is obvious:
>>> numbers + strings + floats
[1, 2, 'three', 'four', 5.0, 6.0]
Functional approach
The same result can be achieved by taking advantage of some standard library
functions. One possible way to sum sequences of the same type is by
cumulatively adding them using the functools.reduce
function:
from functools import reduce
data = [numbers, strings, floats]
>>> reduce(lambda x, y: x + y, data)
[1, 2, 'three', 'four', 5.0, 6.0]
or
>>> from operator import add
>>> reduce(add, data)
[1, 2, 'three', 'four', 5.0, 6.0]
Alternatively, the built-in function sum
can be used as well:
>>> sum(data, [])
[1, 2, 'three', 'four', 5.0, 6.0]
Note: the official documentation suggests to use
itertools.chain
rather than sum
to concatenate iterables.
Final note
All solutions shown in the first section can also be used to join sequences retrieved from iterators. For example:
>>> [*map(int, '12'), *(2**n for n in (2, 3))]
[1, 2, 4, 8]
(Technically, iterators themselves are not considered
sequences as they don’t support indexing, slicing and len
)