Slicing and Striding Lists
Table of Contents
Slicing
Two things to note:
- Python is zero-based indexed. Eg. a list with 5 elements, will be indexed from 0 to 4.
- Intervals are closed from the left and open from the right.
Entire list
l = list(range(15))
print(l)
# [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
assert l == l[:] == l[0 : len(l)]
First n
n = 5
print(f"First {n} elements:", l[:n])
# First 5 elements: [0, 1, 2, 3, 4]
Last n
n = 5
print(f"Last {n} elements:", l[-n:])
# Last 5 elements: [10, 11, 12, 13, 14]
From element i to element j
i, j = 5, 10
print(f"From index {i} to {j}:", l[i:j])
# From index 5 to 10: [5, 6, 7, 8, 9]
From n, excluding last m
n = m = 5
print(f"From {n} and exclude last {m}:", l[n:-m])
# From 5 and exclude last 5: [5, 6, 7, 8, 9]
Last n, excluding last m
n, m = 5, 3
print(f"Last {n} excluding last {m}:", l[-n:-m])
# Last 5 excluding last 3: [10, 11]
Overwriting a smaller slice with a larger list
a = [1, 2, 3, 4, 5]
print(a[2:4]) # [3, 4]
a[2:4] = ["nul", "ett", "to", "tre", "fire", "fem"]
print(a)
# [1, 2, 'nul', 'ett', 'to', 'tre', 'fire', 'fem', 5]
Overwriting a larger slice with a smaller list
a = [1, 2, 3, 4, 5]
print(a[1:-1]) # [2, 3, 4]
a[1:-1] = ["null"]
print(a)
# [1, 'null', 5]
Copy contents (diff memory address). Changes in A/B don’t change B/A
A = ["u", "w", "x", "y", "z"]
B = A[:] # assign the contents of A to a new object B
assert B == A and B is not A
B = B[:2] # a new memory address for B is created
# B after re-assigning B
print(B) # ['u', 'w']
# A after re-assigning B
print(A) # ['u', 'w', 'x', 'y', 'z']
assert B != A
Copy objects (diff memory address). Changes in A/B don’t change B/A
A = ["u", "w", "x", "y", "z"]
B = A # create a copy of object A. shared memory address
assert A is B
assert hex(id(A)) == hex(id(B)) # same location in memory
A = A[:2] # a new memory address for A is created
assert hex(id(A)) != hex(id(B))
# A after re-assigning A
print(A) # ['u', 'w']
# B after re-assgining A
print(B) # ['u', 'w', 'x', 'y', 'z']
assert B is not A and B != A
Creating a copy of A as B. Overwriting A/B also changes B/A
A = ["u", "w", "x", "y", "z"]
B = A # create a copy of object A. shared memory address
assert A is B
A[:] = ["1k", "2k", "3k"] # A is overwritten, which means B is also
# A after overwriting A
print(A) # ['1k', '2k', '3k']
# B after overwriting A
print(B) # ['1k', '2k', '3k']
assert A is B
assert hex(id(A)) == hex(id(B)) # same location in memory
Striding: list[start:end:stride]
Odd indices (1, 3, 5, …)
pp = ["electron", "muon", "tau", "gluon", "photon", "strange"]
odd_indices = pp[1::2]
print(odd_indices)
# ['muon', 'gluon', 'strange']
Even indices (0, 2, 4, …)
even_indices = pp[::2]
print(even_indices)
# ['electron', 'tau', 'photon']
Reversing an iterable
print(pp[::-1])
# ['strange', 'photon', 'gluon', 'tau', 'muon', 'electron']
palindrome = "kayak"
assert palindrome == palindrome[::-1]
Reverse and take every second element
nums = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
print(nums[::-2]) # [9, 7, 5, 3, 1]
# in two steps for more clarity: first reverse, then stride
nums_reversed = nums[::-1]
print(nums_reversed[::2]) # [9, 7, 5, 3, 1]
assert nums[::-2] == nums_reversed[::2]