LambdaLabTM
Computer Science · Class 11 · Lists Revisited
ListsPositions⏱️ 15 min read

Traversal by Index

for i in range(len(marks)): — longer to write, and the only form that can do four things: change the list, say where an item is, compare an item with its neighbour, and read two lists at the same place. The first of those is new; a string could never be changed at all.

1Program 1 — five grace marks for everybody

📋 The problem

Raise every mark in a list by 5, in the list itself.

grace_marks.py
# give every mark 5 grace marks, in the list itself

marks = [56, 91, 43, 78]

print('Before:', marks)

for i in range(len(marks)):
    marks[i] = marks[i] + 5

print('After: ', marks)
Output
Before: [56, 91, 43, 78]
After:  [61, 96, 48, 83]
for i in range(len(marks)):

len(marks) is 4, so range(4) hands out 0, 1, 2, 3 — exactly the valid positions. Positions start at 0 and range() leaves its stop out, and the two rules cancel.

marks[i] = marks[i] + 5

Read the right-hand side first: fetch the item at position i and add 5. Then the = writes that answer back INTO position i. The list itself is different afterwards.

Watch Out
The original values are gone. This program edits the list rather than copying it, so nothing afterwards can see the marks as they were. If the old values still matter, build a new list instead — that is the third column of the widget on the first page of this submenu.

2Program 2 — replace, but only some of them

📋 The problem

Every mark below 33 is to be recorded as 0.

fail_to_zero.py
# replace every failing mark with 0

marks = [72, 28, 88, 15, 54]

for i in range(len(marks)):
    if marks[i] < 33:
        marks[i] = 0

print(marks)
Output
[72, 0, 88, 0, 54]

Note what the if is testing: marks[i], the item, while the assignment writes to marks[i], the place. The same expression means “the value there” on the right of an = and “the box there” on the left. There is no else, and none is needed: an item that fails the test is simply left as it is, because nothing is being built.

3Program 3 — is the list in order?

📋 The problem

Say whether a list is sorted, by checking every item against the one after it.

in_order.py
# is the list already in order?

numbers = [3, 8, 12, 12, 20]
sorted_so_far = True

for i in range(len(numbers) - 1):
    if numbers[i] > numbers[i + 1]:
        sorted_so_far = False

if sorted_so_far:
    print('The list is in order')
else:
    print('The list is not in order')
Output
The list is in order
in_order.py — with numbers = [3, 20, 12]
Output
The list is not in order
Key Takeaway
A body that uses numbers[i + 1] must stop one early. range(len(numbers) - 1) — because the last position has nothing after it, and asking for it raises IndexError: list index out of range. This is not the off-by-one mistake; it is the correction for reaching forward. Reaching backwards with numbers[i - 1] costs the same round at the other end: the loop must start at 1.

The test is > rather than >=, so the repeated 12 does not count as out of order — a sorted list is allowed equal neighbours. That single character decides whether [3, 12, 12, 20] passes.

4Program 4 — two lists, read together

📋 The problem

One list holds names and another holds their marks, in the same order. Print each name with its mark.

names_marks.py
# two lists, read at the same position

names = ['Asha', 'Ravi', 'Meera', 'Karan']
marks = [72, 65, 88, 91]

for i in range(len(names)):
    print(names[i], 'scored', marks[i])
Output
Asha scored 72
Ravi scored 65
Meera scored 88
Karan scored 91
Key Takeaway
One number, two lists. Lists used together like this are called parallel lists: position 2 means Meera in one and 88 in the other, and that agreement is the only thing tying them together. A loop variable holding an item could never do this — it can only be in one list at a time.
Watch Out
Nothing enforces the agreement. Append a name and forget the mark, and marks[i] raises IndexError on the last round — or worse, silently pairs the wrong mark with the wrong name if a value was inserted in the middle. A dictionary keeps the pairing in one place and cannot drift; parallel lists are what you use before you reach for one.

5Program 5 — reverse a list in place

📋 The problem

Reverse a list without reverse() and without building a second list — by swapping items from the two ends inwards.

reverse_in_place.py
# reverse a list in place, by swapping from both ends

numbers = [10, 20, 30, 40, 50]

print('Before:', numbers)

for i in range(len(numbers) // 2):
    last = len(numbers) - 1 - i

    temp = numbers[i]
    numbers[i] = numbers[last]
    numbers[last] = temp

print('After: ', numbers)
Output
Before: [10, 20, 30, 40, 50]
After:  [50, 40, 30, 20, 10]
for i in range(len(numbers) // 2):

Half the length, floor-divided. Each round swaps a PAIR, so running the whole way would swap everything back and leave the list exactly as it started. With five items that is range(2) — and the middle item never needs to move.

last = len(numbers) - 1 - i

The partner of position i, counted from the other end: 0 pairs with 4, 1 pairs with 3. Naming it is what keeps the three swap lines readable.

temp = numbers[i]

The third box, from the swap program in Sample Programs. Without it, the first assignment overwrites the value the second one needs and both places end up holding the same number.

Watch Out
Run the loop the whole way and the list comes back unchanged. range(len(numbers)) swaps every pair twice — once from each end — so the second swap undoes the first. No error, and the program looks like it did nothing, which is exactly what makes it hard to spot.

Python has numbers.reverse(), which does this in place in one call, and numbers[::-1], which hands back a reversed copy. Know all three: the difference between the last two is whether the original changes, and that is a question papers ask directly.

reverse_in_place.py

6Recap

marks[i] = … writes into the list

The same expression is a value on the right of the = and a place on the left. This is the only way a loop can change a list.

Reaching forward shortens the loop

numbers[i + 1] means stopping at len - 1; numbers[i - 1] means starting at 1. Both errors land on the first or last round only.

One number can index two lists

Parallel lists agree by position and nothing enforces it — a dictionary is what you use when the pairing must not drift.

Swapping needs a temp, and half the loop

Three lines with a third box, and range(len // 2) — going the whole way swaps every pair twice and undoes itself.

✍️ Now write these yourself
  1. 1

    Double every number in a list, in place.

    Hint · numbers[i] = numbers[i] * 2 — program 1 with a different sum.

  2. 2

    Replace every negative reading with 0, and count how many you replaced.

    Hint · Program 2 with a counter beside the assignment, inside the same if.

  3. 3

    Report every position where a list of temperatures rose from one day to the next.

    Hint · temps[i + 1] > temps[i], and stop the loop one early.

  4. 4

    Given parallel lists of items and prices, print each line and the bill total.

    Hint · One loop over the positions, a print() and a running total inside it.

  5. 5

    Swap the first half of a list with the second half — for an even length only.

    Hint · Pair position i with i + len(numbers) // 2, and loop over half the length.

Quick Check

Which line changes the list itself?

Quick Check

A loop compares numbers[i] with numbers[i + 1]. What must its range be?

Quick Check

A reverse-by-swapping program uses range(len(numbers)) instead of range(len(numbers) // 2). What happens?