Python Nested List

Nested lists in Python are lists that contain other lists as their elements. This structure allows you to create multi-dimensional data representations, which are particularly useful when working with matrices, tables, or other complex data arrangements.

Let’s learn more about nested lists in Python and explore various operations and techniques for working with them.

Creating a Nested List

A nested list can be created by placing lists within a list. Here are some basic examples:

# Basic nested list
L = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]

# Nested list with different lengths of inner lists
L = [[1, 2], [3, 4, 5], [6, 7, 8, 9]]

# Nested list with mixed data types
L = [["Alice", 30], ["Bob", 25], ["Charlie", 35]]

# Deeper nested lists
L = ['a', 'b', ['cc', 'dd', ['eee', 'fff']], 'g', 'h']

Accessing Elements in a Nested List

To access elements in a nested list, you use multiple indices – one for each level of the list. The first index specifies which of the inner lists to access, and the subsequent indices specify the element within that inner list.

The indexes for the elements in a nested list are illustrated as below:

python nested list indexing
L = ['a', 'b', ['cc', 'dd', ['eee', 'fff']], 'g', 'h']

print(L[2])         # Output: ['cc', 'dd', ['eee', 'fff']]
print(L[2][2])      # Output: ['eee', 'fff']
print(L[2][2][0])   # Output: eee

In this list, L[2] accesses the third element, which is itself a list: ['cc', 'dd', ['eee', 'fff']]. To get to ‘eee’, we need another index: L[2][2] gets us to the third element of this inner list, which is yet another list: ['eee', 'fff']. Finally, L[2][2][0] gives us the first element of this innermost list, which is the string ‘eee’.

Negative List Indexing In a Nested List

In Python, negative indexing provides a convenient way to access elements from the end of a list. Just like positive indices start from 0 and count upwards, negative indices start from -1 and count downwards. So, -1 refers to the last element, -2 to the second-last, and so on.

This concept also applies to nested lists, where each level of nesting can be accessed with its own negative index.

The negative indexes for the elements in a nested list are illustrated as below:

python nested list negative indexing
L = ['a', 'b', ['cc', 'dd', ['eee', 'fff']], 'g', 'h']

print(L[-3])           # Output: ['cc', 'dd', ['eee', 'fff']]
print(L[-3][-1])       # Output: ['eee', 'fff']
print(L[-3][-1][-2])   # Output: eee

Modifying Elements in a Nested List

Just like with regular lists, You can modify elements in nested lists by specifying the indices of the element you want to change:

L = ['a', ['bb', 'cc'], 'd']
L[1][1] = 0
print(L)
# Output: ['a', ['bb', 0], 'd']

Adding Elements to a Nested List

Nested lists in Python can be modified using the same list operations as regular lists. This means you can add elements to nested lists using methods like append(), insert(), and extend().

To add a new element to the end of a nested list, you can use the append() method.

L = ['a', ['bb', 'cc'], 'd']
L[1].append('xx')
print(L)
# Output: ['a', ['bb', 'cc', 'xx'], 'd']

If you need to insert an element at a specific position within a nested list, the insert() method is the right tool.

L = ['a', ['bb', 'cc'], 'd']
L[1].insert(0,'xx')
print(L)
# Output: ['a', ['xx', 'bb', 'cc'], 'd']

Finally, the extend() method allows you to merge one list into another.

L = ['a', ['bb', 'cc'], 'd']
L[1].extend([1, 2, 3])
print(L)
# Output: ['a', ['bb', 'cc', 1, 2, 3], 'd']

Removing Elements from a Nested List

There are different ways to remove elements from a nested list depending on your specific needs.

If you know the index of the element you want to remove, the pop() method is a good choice. This method not only removes the element at the specified index but also returns its value.

L = ['a', ['bb', 'cc', 'dd'], 'e']
x = L[1].pop(1)
print(L)
# Output: ['a', ['bb', 'dd'], 'e']

# removed element
print(x)
# Output: cc

In cases where you don’t need the removed value, the del statement is a simple and efficient way to delete an element by its index.

L = ['a', ['bb', 'cc', 'dd'], 'e']
del L[1][1]
print(L)
# Output: ['a', ['bb', 'dd'], 'e']

If you don’t know the exact index but know the value of the element you want to remove, the remove() method is the way to go. This method searches the list and removes the first occurrence of the specified value.

L = ['a', ['bb', 'cc', 'dd'], 'e']
L[1].remove('cc')
print(L)
# Output: ['a', ['bb', 'dd'], 'e']

Finding the Length of a Nested List

Determining the number of elements within a nested list is simple using Python’s built-in len() function. This function returns the length of a list, which is the number of elements it contains.

L = ['a', ['bb', 'cc'], 'd']

print(len(L))      # Output: 3
print(len(L[1]))   # Output: 2

Iterating Through a Nested List

You can iterate through nested lists using nested loops. In this approach, an outer loop iterates over the sublists within the main list, while an inner loop iterates over the individual elements within each sublist.

L = [[1, 2, 3],[4, 5, 6],[7, 8, 9]]   
for list in L:
    for number in list:
        print(number, end=' ')
# Output: 1 2 3 4 5 6 7 8 9

Common Use Cases for Nested Lists

Nested lists provide a powerful and flexible way to organize and structure data in a hierarchical manner.

Matrices and 2D Arrays

One common use case is representing matrices and 2D arrays, which are useful in mathematical computations and data science.

matrix = [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
]

Tables of Data

Nested lists are also used to represent tabular data; each inner list can act as a row, with elements representing the data within each column.

table = [
    ["Name", "Age", "Occupation"],
    ["Alice", 30, "Engineer"],
    ["Bob", 25, "Artist"]
]

Graphs and Trees

Even in more complex scenarios, such as graph theory or data structures, nested lists can be useful. In graph representation, nested lists can store adjacency lists, where each inner list contains the neighbors of a particular node.

graph = [
    [1, 2],    # Neighbors of node 0
    [0, 3],    # Neighbors of node 1
    [0, 3],    # Neighbors of node 2
    [1, 2]     # Neighbors of node 3
]