Introduction
A list is the most flexible data structure in Python. Whereas, a 2D list which is commonly known as a list of lists, is a list object where every item is a list itself - for example: [[1,2,3], [4,5,6], [7,8,9]]
.
Flattening a list of lists entails converting a 2D list into a 1D list by un-nesting each list item stored in the list of lists - i.e., converting [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
into [1, 2, 3, 4, 5, 6, 7, 8, 9]
.
The process of flattening can be performed using nested for loops, list comprehensions, recursion, built-in functions or by importing libraries in Python depending on the regularity and depth of the nested lists.
Types of Nested Lists
Since Python is weakly typed, you can encounter regular and irregular lists of lists.
Regular List of Lists
Every element of this list is a sublist, thereby adhering to the uniformity of the element type.
Example: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
is a regular list of lists as [1, 2, 3], [4, 5, 6], [7, 8, 9]
is of type list
.
Irregular List of Lists
Every element of this list is either a sublist or a non-list item (for example an integer or string). Therefore, there is an irregularity in terms of the element type. Example: [[1, 2, 3], [4, 5], 6]
where [1, 2, 3]
and [4, 5]
are of type list
and 6
is of type int
.
Flatten List of Lists Using Nested for Loops
This is a brute force approach to obtaining a flat list by picking every element from the list of lists and putting it in a 1D list.
The code is intuitive as shown below and works for both regular and irregular lists of lists:
def flatten_list(_2d_list):
flat_list = []
# Iterate through the outer list
for element in _2d_list:
if type(element) is list:
# If the element is of type list, iterate through the sublist
for item in element:
flat_list.append(item)
else:
flat_list.append(element)
return flat_list
nested_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
print('Original List', nested_list)
print('Transformed Flat List', flatten_list(nested_list))
This results in:
Original List [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
Transformed Flat List [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Flatten List of Lists Using a List Comprehension
This approach provides an elegant but a less intuitive solution to create a flat list based on an existing 2D list:
regular_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
flat_list = [item for sublist in regular_list for item in sublist]
print('Original list', regular_list)
print('Transformed list', flat_list)
Which would output the following:
Original list [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
Transformed list [1, 2, 3, 4, 5, 6, 7, 8, 9]
Flatten List of Lists Recursively
The 2D list can be flattened recursively as well. The implementation below works both for regular and irregular list of lists:
def flatten(list_of_lists):
if len(list_of_lists) == 0:
return list_of_lists
if isinstance(list_of_lists[0], list):
return flatten(list_of_lists[0]) + flatten(list_of_lists[1:])
return list_of_lists[:1] + flatten(list_of_lists[1:])
print(flatten([[1, 2, 3, 4], [5, 6, 7], [8, 9], 10]))
Which would give us:
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Using Libraries
You can also rely on the help of Pyhon libraries for this task.
Flatten List of Lists Using functools (reduce() and iconcat())
The iconcat()
function performs the basic operation of concatenation and is applied cumulatively to the items of a list of lists, from left to right, so as to reduce it to a single list:
import functools
import operator
regular_list = []
# Transform irregular 2D list into a regular one.
def transform(nested_list):
for ele in nested_list:
if type(ele) is list:
regular_list.append(ele)
else:
regular_list.append([ele])
return regular_list
irregular_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10], 11]
regular_2D_list = transform(irregular_list)
print('Original list', irregular_list)
print('Transformed list', functools.reduce(operator.iconcat, regular_2D_list, []))
Which would give us the desired result:
Original list [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10], 11]
Transformed list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
Flatten List of Lists Using itertools (chain())
This approach is ideal for transforming a 2-D list into a single flat list as it treats consecutive sequences as a single sequence by iterating through the iterable passed as the argument in a sequential manner.
import itertools
regular_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
flat_list = list(itertools.chain(*regular_list))
print('Original list', regular_list)
print('Transformed list', flat_list)
Again, this would give us a flattened list as the output:
Original list [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
Transformed list [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
Flatten List of Lists Using numpy (concatenate() and flat())
Numpy offers common operations which include concatenating regular 2D arrays row-wise or column-wise. We are also using the flat
attribute to get a 1D iterator over the array in order to achieve our goal. However, this approach is relatively slow:
import numpy
regular_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
flat_list = list(numpy.concatenate(regular_list).flat)
print('Original list', regular_list)
print('Transformed list', flat_list)
Which gives us the desired output:
Original list [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
Transformed list [1, 2, 3, 4, 5, 6, 7, 8, 9]
Using Built-In Functions
The task of flattening can also be performed by using built-in functions that Python offers.
Flatten List of Lists Using sum
Summing over inner lists is another solution. The function has two parameters: iterable
which is a list of lists and start
which is an empty list in our case that serves as the initial flat list to which items of the inner sublists are added.
This approach is convenient as you don't have to import anything but it's slower than itertools()
and the chain()
functions when the number of sublists is large:
regular_list = [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
flat_list = sum(regular_list, [])
print('Original list', regular_list)
print('Transformed list', flat_list)
With the output:
Original list [[1, 2, 3, 4], [5, 6, 7], [8, 9]]
Transformed list [1, 2, 3, 4, 5, 6, 7, 8, 9]
Flatten List of Lists Using Lambda
An anonymous function can be defined using the lambda keyword. The regular/irregular list is passed as the argument to this anonymous function and the evaluation of the expression is done to obtain a flat 1D list:
irregular_list = [[1, 2, 3], [3, 6, 7], [7, 5, 4],7]
# Using lambda arguments: expression
flatten_list = lambda irregular_list:[element for item in irregular_list for element in flatten_list(item)] if type(irregular_list) is list else [irregular_list]
print("Original list ", irregular_list)
print("Transformed List ", flatten_list(irregular_list))
We would again get the desired result:
Original list [[1, 2, 3], [3, 6, 7], [7, 5, 4], 7]
Transformed List [1, 2, 3, 3, 6, 7, 7, 5, 4, 7]
Conclusion
In this article, we provided an extensive list of ways we can complete the task of flattening a list of lists in Python.
from Planet Python
via read more
No comments:
Post a Comment