Skip to content

Lists snippets

Small patterns for lists that come up often in the exercises. Each one is short on purpose: the case it solves, the syntax, and the result.

When you need the elements in reverse without a loop.

nums = [1, 2, 3, 4]
nums[::-1] # → [4, 3, 2, 1] new list, original untouched
"hello"[::-1] # → "olleh" works on strings too

[::-1] is a slice with step -1. It builds a new object, so the original stays as it is.

When you want the elements of one list followed by another, in a new list.

[1, 2, 3] + [4, 5] # → [1, 2, 3, 4, 5] new list, both inputs untouched
# combining slices of the same list is how you rotate it
nums = [1, 2, 3, 4, 5]
k = 2
nums[-k:] + nums[:-k] # → [4, 5, 1, 2, 3] tail (last k) in front of the head

+ always builds a new list and leaves the originals alone. To grow a list in place instead, use a += b or a.extend(b).

When the loop needs the position as well as the value. Prefer this over range(len(...)).

for i, value in enumerate(["a", "b", "c"]):
print(i, value) # 0 a / 1 b / 2 c
# start= shifts the counter without touching the data
for i, value in enumerate(["a", "b", "c"], start=1):
print(i, value) # 1 a / 2 b / 3 c

When you need matching elements from two lists at once. It stops at the shorter one.

names = ["ann", "bob", "cate"]
scores = [90, 75, 88]
for name, score in zip(names, scores):
print(name, score) # ann 90 / bob 75 / cate 88

When you want unique elements but still in their first-seen order. A plain set() loses the order, dict.fromkeys does not.

list(dict.fromkeys([3, 1, 3, 2, 1])) # → [3, 1, 2]

Since Python 3.7 a dict keeps insertion order, so the keys come back in the order they first appeared.

When you have a list of lists and want one flat list.

nested = [[1, 2], [3, 4], [5]]
[n for row in nested for n in row] # → [1, 2, 3, 4, 5]

Read the two for clauses left to right, like nested loops: the outer picks each row, the inner walks its numbers.

When the order depends on something other than the values themselves.

words = ["bb", "a", "ccc"]
sorted(words, key=len) # → ["a", "bb", "ccc"] by length
pairs = [("bob", 2), ("ann", 1)]
sorted(pairs, key=lambda p: p[1]) # → [("ann", 1), ("bob", 2)] by second field

sorted returns a new list. Use list.sort(key=...) to sort in place.

When you want a separate list you can change without touching the original.

nums = [1, 2, 3]
copy = nums[:] # nums[:] is a full slice, start to end, so it builds a NEW list
copy.append(4)
print(copy) # [1, 2, 3, 4]
print(nums) # [1, 2, 3] the original is untouched

The difference between nums[:] and plain nums: nums[:] makes a copy, nums does not. Assigning nums to another name gives you a second label for the same list, so changing one changes the other.

same = nums # NOT a copy, just another name for the same list
same.append(4)
print(nums) # [1, 2, 3, 4] changed through "same"

nums[:], nums.copy(), and list(nums) all produce the same real copy; pick whichever reads best. This is a shallow copy: the outer list is separate, but if it holds inner lists or dicts, those are still shared. Use copy.deepcopy(nums) when you need the inner objects duplicated too.