Module 2 · Lesson 3

Fancy Indexing

“Fancy indexing” means indexing with an array (or list) of integers instead of a single index or a slice. It lets you pick out an arbitrary, possibly repeated, possibly reordered set of elements/rows/columns in one shot. You can combine a fancy index on one axis with a slice on another. Unlike basic slicing, fancy indexing always returns a copy, never a view.

arr = np.array([10, 20, 30, 40, 50])
print(arr[[0, 2, 4]])        # pick specific elements
print(arr[[3, 3, 1]])        # repeats allowed, any order

grid = np.arange(12).reshape(4, 3)
print(grid[[0, 2]])          # rows 0 and 2
print(grid[[0, 2], :2])      # rows 0 and 2, first two columns
print(grid[[0, 1, 2], [0, 1, 2]])  # (0,0), (1,1), (2,2) -- paired coordinates!

Output:

[10 30 50]
[40 40 20]
[[0 1 2]
 [6 7 8]]
[[0 1]
 [6 7]]
[0 4 8]
3.1

Reorder rows

Write reorder_rows(grid, order) that takes a 2-D array and a list of row indices order, and returns a new array with the rows rearranged into that order (rows may repeat or be dropped).

💡 Hint

Fancy-index the row axis directly: grid[order].

✅ Solution
def reorder_rows(grid, order):
    return grid[order]
3.2

Diagonal via coordinates

Write pick_diagonal(grid) that returns the main diagonal of a square 2-D array using paired fancy indexing (grid[rows, cols]), not np.diagonal or np.diag.

💡 Hint

Build row and column index arrays with np.arange(len(grid)) and use them both: grid[idx, idx].

✅ Solution
def pick_diagonal(grid):
    idx = np.arange(len(grid))
    return grid[idx, idx]