Skip to main content
โšก Calmops

2D Arrays in Python: Lists, NumPy, and Common Operations

Introduction

Two-dimensional arrays (matrices) are fundamental data structures in Python โ€” used for grids, images, game boards, mathematical matrices, and tabular data. Python offers several ways to create and work with 2D arrays, from plain lists of lists to NumPy arrays.

Creating 2D Arrays with List Comprehension

The corra 2D list:

rows = 4
cols = 3

# Correct: list comprehension creates independent rows
table = [[0] * cols for _ in range(rows)]
print(table)
# => [[0, 0, 0], [0, 0, 0], [0, 0, 0], [0, 0, 0]]

The Common Pitfall: Shared References

Never use [[value] * cols] * rows โ€” all rows will be the same object:

# WRONG: all rows share the same list object
table = [[0] * cols] * rows
table[1][1] = 99
print(table)
# => [[0, 99, 0], [0, 99, 0], [0, 99, 0], [0, 99, 0]]
# Changing rnged ALL rows!

# CORRECT: each row is a separate list
table = [[0] * cols for _ in range(rows)]
table[1][1] = 99
print(table)
# => [[0, 0, 0], [0, 99, 0], [0, 0, 0], [0, 0, 0]]

Initialize with Different Values

# All zeros
zeros = [[0] * 5 for _ in range(3)]

# All None
grid = [[None] * 5 for _ in range(3)]

# Sequential values
matrix = [[i * cols + j for j in range(cols)] for i in range(rows)]
# => [[0, 1, 2], [3, 4, 5], [6, 7, 8], [9, 10, 11]]

# Identity matrix
n = 4
 else 0 for j in range(n)] for i in range(n)]
# => [[1,0,0,0], [0,1,0,0], [0,0,1,0], [0,0,0,1]]

| Homogeneous | | Best for | Small grids, game boards | Math, images, ML |

Resources

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

print(spiral_order(m))

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


## List of Lists vs NumPy: When to Use Each

| Feature | List of Lists | NumPy Array |
|---|---|---|
| Creation | Simple, no imports | Requires NumPy |
| Performance | Slow for math | Fast (C-optimized) |
| Memory | Higher | Lower |
| Vectorized ops | No (need loops) | Yes |
| Slicing | Limited | Powerful |
| Data types | Mixedvalues (0-255)
image = np.random.randint(0, 256, size=(100, 100), dtype=np.uint8)

# Flip horizontally
flipped = image[:, ::-1]

# Crop
cropped = image[10:50, 20:60]

# Threshold (binary)
binary = (image > 128).astype(np.uint8) * 255

# Resize (simple nearest-neighbor)
small = image[::2, ::2]  # every other pixel

Spiral Matrix

def spiral_order(matrix):
    """Return elements of matrix in spiral order."""
    result = []
    while matrix:
        result += matrix.pop(0)  # top row
       )

```python
# Initialize empty board
board = [['.' for _ in range(3)] for _ in range(3)]

def print_board(board):
    for row in board:
        print(' '.join(row))
    print()

def make_move(board, row, col, player):
    if board[row][col] == '.':
        board[row][col] = player
        return True
    return False

make_move(board, 1, 1, 'X')
make_move(board, 0, 0, 'O')
print_board(board)
# O . .
# . X .
# . . .

Image as 2D Array

import numpy as np

# Grayscale image: 2D array of pixel      # => 3  (flat index of max)

Reshaping

flat = np.arange(12)  # [0, 1, 2, ..., 11]

# Reshape to 3x4
m = flat.reshape(3, 4)
print(m)
# [[ 0  1  2  3]
#  [ 4  5  6  7]
#  [ 8  9 10 11]]

# -1 means "infer this dimension"
m2 = flat.reshape(-1, 3)  # shape: (4, 3)
m3 = flat.reshape(2, -1)  # shape: (2, 6)

# Flatten back
print(m.flatten())   # => [ 0  1  2  3  4  5  6  7  8  9 10 11]
print(m.ravel())     # same but may return a view

Practical Examples

Game Board (Tic-Tac-Toe 6], [7, 8]])

Element-wise operations

print(a + b) # => [[ 6 8], [10 12]] print(a * b) # => [[ 5 12], [21 32]] print(a ** 2) # => [[ 1 4], [ 9 16]]

Matrix multiplication

print(a @ b) # => [[19 22], [43 50]] print(np.dot(a, b)) # same

Transpose

print(a.T) # => [[1 3], [2 4]]

Statistics

print(a.sum()) # => 10 print(a.sum(axis=0)) # => [4 6] (column sums) print(a.sum(axis=1)) # => [3 7] (row sums) print(a.mean()) # => 2.5 print(a.max()) # => 4 print(a.argmax())thon m = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])

Single element

print(m[1, 2]) # => 6 (row 1, col 2)

Row slice

print(m[1, :]) # => [4 5 6] (entire row 1) print(m[0:2, :]) # => [[1 2 3], [4 5 6]] (rows 0-1)

Column slice

print(m[:, 1]) # => [2 5 8] (entire column 1) print(m[:, 1:3]) # => [[2 3], [5 6], [8 9]] (columns 1-2)

Boolean indexing

print(m[m > 5]) # => [6 7 8 9]


### NumPy Operations

```python
a = np.array([[1, 2], [3, 4]])
b = np.array([[5,```python
import numpy as np

# Create arrays
zeros   = np.zeros((4, 3))          # 4x3 array of 0.0
ones    = np.ones((3, 3))           # 3x3 array of 1.0
full    = np.full((2, 4), 7)        # 2x4 array of 7
eye     = np.eye(4)                 # 4x4 identity matrix
random  = np.random.rand(3, 3)      # 3x3 random floats [0,1)
arange  = np.arange(12).reshape(3, 4)  # [[0,1,2,3],[4,5,6,7],[8,9,10,11]]

print(zeros)
# [[0. 0. 0.]
#  [0. 0. 0.]
#  [0. 0. 0.]
#  [0. 0. 0.]]

NumPy Indexing and Slicing


# Using itertools
import itertools
flat = list(itertools.chain.from_iterable(matrix))

Rotate 90 Degrees

def rotate_90_clockwise(matrix):
    return [list(row) for row in zip(*matrix[::-1])]

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

print(rotate_90_clockwise(m))
# => [[7, 4, 1], [8, 5, 2], [9, 6, 3]]

NumPy arrays are faster, more memory-efficient, and support vectorized operations:

99 2 3 4 5 6 7 8 9

Iterate with indices

for i, row in enumerate(matrix): for j, val in enumerate(row): print(f"[{i}][{j}]={val}", end=" “)


## Common 2D Array Operations

### Transpose

```python
matrix = [[1, 2, 3],
          [4, 5, 6]]

# Using zip
transposed = [list(row) for row in zip(*matrix)]
print(transposed)
# => [[1, 4], [2, 5], [3, 6]]

Flatten

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

# Using list comprehension
flat = [val for row in matrix for val in row]
printg Elements

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

# Access element at row 1, col 2
print(matrix[1][2])  # => 6

# Modify element
matrix[0][0] = 99
print(matrix[0])  # => [99, 2, 3]

# Get a full row
print(matrix[1])  # => [4, 5, 6]

# Get a full column (no direct syntax โ€” use list comprehension)
col = [matrix[row][1] for row in range(len(matrix))]
print(col)  # => [2, 5, 8]

# Iterate over all elements
for row in matrix:
    for val in row:
        print(val, end=" ")
# =
## Accessing and Modifyin

Comments