Explain Codes LogoExplain Codes Logo

How to define a two-dimensional array in Python?

python
list-comprehensions
numpy
best-practices
Nikita BarsukovbyNikita Barsukov·Oct 1, 2024
TLDR

Here's the Pythonic way to create a two-dimensional array, or matrix, with a nested list comprehension:

# Here's your matrix, as easy as a lazy Sunday morning two_dim_array = [[0]*3 for _ in range(3)]

This creates a 3x3 matrix, filled with zeros. To access elements, use the syntax two_dim_array[row][column].

Decoding matrix initialization

Efficient accessibility and proper error handling can make or break your code. Let's conquer potential pitfalls and you can claim the high ground of Pythonista proficiency.

Craft distinct rows in your matrix

Do not initiate a 2D array with repeated sub-lists (eg: buggy_matrix = [[0]*3] * 3). You might end up in a shared nightmare, where all rows repeat the same values:

buggy_matrix[0][0] = 99 print(buggy_matrix) # Output: [[99, 0, 0], [99, 0, 0], [99, 0, 0]] # Look, unexpected surprises, just like my first date

Instead, use a list comprehension to create independent rows:

cool_matrix = [[0]*3 for _ in range(3)]

Flexible initialization with comprehensions

List comprehensions also enable dynamic initializations, allowing you to insert diverse values or to run functions:

magic_matrix = [[f(x, y) for x in range(width)] for y in range(height)] # Now you're a wizard, Harry

In this case, f(x, y) returns the initial value for the coordinates (x, y).

Making magic with large data sets

Working with bigger matrices? Python lists sometimes just don't cut it. Thankfully, high-performance libraries have got your back.

NumPy to the data-rescue

NumPy is the hero we need, offering functions like zeros, ones, empty, and arange that let you make matrices in a snap:

import numpy as np your_matrix = np.zeros((3, 3)) # Just like at the DMV, we get heaps of zeros here

Sparse matrices: mastering the art of emptiness

If your matrix is predestined to be mostly zeroes, using sparse matrix representations is the way to go:

from collections import defaultdict sparse_matrix = defaultdict(int) # Because nobody got time to store all those zeroes!

With the utilization of sparse_matrix[(y, x)] = value, we can save storage and computation time by storing only non-zero elements.

Troubleshooting

In this ever-practical section, let's heal common wounds with the band-aids of best practices.

Prevent the sneaky IndexError

Before you access elements, do a quick bounds check. Trust me, you don't want to meet the infamous IndexError in a dark alley.

Tuple index: the stable friend you deserve

When you pair dictionaries with sparse matrices, use friendly immutable tuples as keys, because unlike your ex, they don't change unpredictably.

Matrix transformations

Your pre-existing list can morph into a 2D array with the power of NumPy transformations:

list_of_lists = [[1, 2], [3, 4], [5, 6]] np_2d_array = np.array(list_of_lists) # Metamorphosis complete, Franz Kafka would be proud

Beware of shared references

Be wary of replicated sub-lists, as a change to one shared sub-list can unfortunately affect all its lookalikes:

tricky_matrix = 3*[2*[0]] tricky_matrix[0][0] = 911 print(tricky_matrix) # Output: [[911, 0], [911, 0], [911, 0]] # See the whole row change? Must be magic, or maybe just Python

In this case, list comprehensions would be the saviour.