Exit slides Esc

Lists

Slide 1 of 78

  1. A game club has a whole row of scores to organize, compare, and improve. Your challenge is to keep related values together, visit every value, and build useful new collections without losing track of the original data.

    By Lesson 3, you will turn a score list into filtered results and running totals with reusable functions.

    • Make a list, read or change an item by position, and add or remove items.

    • Visit list items in a loop and take a slice of a list.

    • Sort a list and find its largest or smallest item by checking items in order.

    • Build a new list containing only items that pass a test.

  2. Lesson 1: Build and Read

    Start the score board

    A list keeps several values in order. Square brackets make a list literal, and commas separate its items.

  3. scores = [3, 1, 2]
    print(scores)

    Output

    [3, 1, 2]
    

    The three scores stay together in their written order.

    An index reaches one position: index 0 is the first position.

  4. print(scores[0])

    Output

    3
    

    Index 0 selects 3, not the whole list. A negative index counts from the end, as it did for strings in Unit 09.

  5. print(scores[-1])

    Output

    2
    

    Index -1 selects the last score, 2. Use len to count the items.

  6. print(len(scores))

    Output

    3
    

    There are three items. Assign through an index to change one existing item.

  7. scores[1] = 5
    print(scores)

    Output

    [3, 5, 2]
    

    The second score changes, and the list is now [3, 5, 2]. A function can take a list and return its first item.

  8. def first_score(scores):
        return scores[0]
    
    print(first_score(scores))

    Output

    3
    

    first_score(scores) returns 3. It expects a nonempty list, because an empty list has no position 0.

  9. Loop over the values

    When you need each value but not its position, loop directly over the list. The loop below visits one score at a time. len(scores) gives the number of items, and sum(scores) gives their total.

  10. def total_with_values(scores):
        total = 0
        for score in scores:
            total = total + score
        return total
    
    def score_report(scores):
        return f"{len(scores)} scores total {sum(scores)}"
    
    print(total_with_values([4, 7, 5]))
    print(score_report([4, 7, 5]))

    Output

    16
    3 scores total 16
    
  11. The calls return 16 and the report 3 scores total 16. The hand-written loop exposes the running total, while sum performs the same common job in one call. A direct value loop is the clearest choice when the positions do not matter.

  12. Build a new list with append

    The method call some_list.append(value) adds one item at the end of a list. Start with an empty list when the answer will be built one item at a time. Each loop trip calculates one new value and appends it.

  13. def double_values(numbers):
        doubled = []
        for number in numbers:
            doubled.append(number * 2)
        return doubled
    
    print(double_values([2, 5, 8]))
    print(double_values([-3, 0, 4]))

    Output

    [4, 10, 16]
    [-6, 0, 8]
    
  14. The calls return [4, 10, 16] and [-6, 0, 8]. The input list supplies the values; the empty doubled list grows with one append call per trip. The function returns a new list.

  15. Change a list in place

    insert(0, value) places a value before the current first item.

  16. line = [4, 7, 9]
    line.insert(0, 2)
    print(line)

    Output

    [2, 4, 7, 9]
    

    The line is now [2, 4, 7, 9]. pop() removes and returns the last item.

  17. last = line.pop()
    print(last, line)

    Output

    9 [2, 4, 7]
    

    last is 9; the line now ends at 7. Give pop an index to remove a different position.

  18. first = line.pop(0)
    print(first, line)

    Output

    2 [4, 7]
    

    first is 2; the line is [4, 7]. remove(value) removes the first matching value.

  19. line.append(4)
    line.remove(4)
    print(line)

    Output

    [7, 4]
    

    Only the first 4 was removed, leaving [7, 4]. index(value) finds the position of the first match.

  20. print(line.index(4))

    Output

    1
    

    The remaining 4 is at index 1. remove and index raise ValueError for a missing value, so check if value in line: first.

  21. Loop over the positions

    Sometimes a calculation needs both the current item and another position. range(len(scores)) supplies every valid index from 0 through one less than the list length. To compare each score with the previous score, begin at index 1.

  22. def score_changes(scores):
        changes = []
        for i in range(1, len(scores)):
            change = scores[i] - scores[i - 1]
            changes.append(change)
        return changes
    
    print(score_changes([8, 11, 10, 15]))
    print(score_changes([6]))

    Output

    [3, -1, 5]
    []
    
  23. The calls return [3, -1, 5] and []. The index loop is useful because scores[i] and scores[i - 1] reach neighboring positions. A one-item list has no pair to compare, so its result stays empty.

  24. Slices and list equality

    A slice selects a section into a new list; the end index is excluded.

  25. print(scores[1:3])

    Output

    [5, 2]
    

    The result is [5, 2]; scores is unchanged. A step of -1 makes a new list in reverse order.

  26. print(scores[::-1])
    print(scores)

    Output

    [2, 5, 3]
    [3, 5, 2]
    

    The reversed list is [2, 5, 3], while scores remains [3, 5, 2]. Two lists compare equal when their items match in the same order.

  27. print([1, 2] == [1, 2], [1, 2] == [2, 1])

    Output

    True False
    

    Python prints True False; changing the order changes the list.

  28. Read several numbers on one line

    split() separates one line at its spaces into a list of strings.

  29. line = "7 3 8"
    parts = line.split()
    print(parts)

    Output

    ['7', '3', '8']
    

    parts is ["7", "3", "8"]; its items are strings. Convert individual pieces before doing arithmetic.

  30. print(int(parts[0]) + int(parts[1]))

    Output

    10
    

    The first two numbers add to 10. To convert every piece, append each converted value in a loop.

  31. numbers = []
    for part in parts:
        numbers.append(int(part))
    print(numbers)

    Output

    [7, 3, 8]
    

    numbers holds [7, 3, 8] as integers. join can put a separator between the string pieces in a list.

  32. print("-".join(parts))

    Output

    7-3-8
    

    The string result is 7-3-8. Here join receives a list of strings; Unit 09 joined letters from one string. A real program can read that line with input().

  33. Try it
    parts = input("Numbers: ").split()
    numbers = []
    for part in parts:
        numbers.append(int(part))
    print(sum(numbers))

    This input cell waits for a line such as 7 3 8 and prints its total. Another common format puts the count first, followed by one number per line.

  34. Try it
    n = int(input("How many numbers? "))
    numbers = []
    for i in range(n):
        numbers.append(int(input("Number: ")))
    print(numbers)

    The second input cell reads exactly n values into one list.

  35. Lesson 2: Order and Choose

    A tournament organizer needs a low-to-high score board and the position of the winning score. Sorting can order the values, but choosing a position requires a careful index loop.

  36. Notice: sort changes a list and returns None

    The list method sort rearranges the existing list in place. Its returned value is None, which means it does not hand back a useful new list. Predict the two printed lines.

  37. nums = [9, 2, 6]
    scores = nums.sort()
    print(nums)
    print(scores)

    Output

    [2, 6, 9]
    None
    
  38. Python prints [2, 6, 9] and then None. The call changed nums, but scores = nums.sort() saved the method's missing return value. This is the None trap: do not assign the result of sort when you want the changed list.

  39. Sort in place when changing the input is the job

    Call sort as its own statement, then return the now-ordered list if the caller needs that value.

  40. def order_in_place(scores):
        scores.sort()
        return scores
    
    print(order_in_place([12, 5, 8]))
    print(order_in_place([-2, -9, -4]))

    Output

    [5, 8, 12]
    [-9, -4, -2]
    
  41. The calls return [5, 8, 12] and [-9, -4, -2]. This function deliberately changes the list it receives. Its name says that in-place change is part of the job.

  42. Use sorted when the original order must stay

    The built-in function sorted(scores) returns a new ordered list. It leaves the original list in its old order.

  43. def ordered_copy(scores):
        return sorted(scores)
    
    original_scores = [14, 7, 11]
    new_order = ordered_copy(original_scores)
    print(original_scores)
    print(new_order)

    Output

    [14, 7, 11]
    [7, 11, 14]
    
  44. Python prints [14, 7, 11] and [7, 11, 14]. Choose sort for an intentional in-place change and sorted for a separate ordered result.

    A real program can read one line of numbers, convert every piece, and print the ordered copy.

  45. Try it
    parts = input("Numbers: ").split()
    numbers = []
    for part in parts:
        numbers.append(int(part))
    print(sorted(numbers))

    sorted returns a new list in low-to-high order.

  46. Built-in list calculations

    For a list with at least one number, min returns its smallest item and max returns its largest item. sum returns the total. These built-ins answer common value questions, but they do not tell you the position of a winning value.

  47. def number_summary(numbers):
        return [min(numbers), max(numbers), sum(numbers)]
    
    print(number_summary([7, 2, 10, 4]))
    print(number_summary([-8, -3, -12]))

    Output

    [2, 10, 23]
    [-12, -3, -23]
    
  48. The calls return [2, 10, 23] and [-12, -3, -23]. The second call is a reminder that the largest negative number is still negative.

  49. Find an extreme by hand

    A hand-written extreme loop remembers the best value seen so far. This function assumes the list has at least one item, so numbers[0] is a real starting value. Never start best at 0: a list of negative numbers might not contain any value as large as 0.

  50. def find_largest(numbers):
        best = numbers[0]
        for number in numbers:
            if number > best:
                best = number
        return best
    
    print(find_largest([5, 12, 9]))
    print(find_largest([-11, -4, -7]))

    Output

    12
    -4
    
  51. The calls return 12 and -4. Seeding from the first item makes the loop correct for negative values too. The built-in max is shorter when only the value matters; the hand-written loop can be adapted when the position matters.

  52. Find the position of the maximum

    An argmax is the position of a largest value. Remember a position rather than the value itself, then compare through list indexes. This function assumes the list has at least one item.

  53. def position_of_largest(numbers):
        best_position = 0
        for i in range(1, len(numbers)):
            if numbers[i] > numbers[best_position]:
                best_position = i
        return best_position
    
    print(position_of_largest([13, 21, 18]))
    print(position_of_largest([-2, -7, -1]))

    Output

    1
    2
    
  54. The calls return 1 and 2. Because the comparison uses > rather than >=, equal largest values leave the earliest winning position in place.

  55. Apply argmax to words

    The same position loop can compare calculated qualities instead of number values. To find the longest word, compare the lengths of the words at two positions. The list must have at least one item.

  56. def position_of_longest(words):
        best_position = 0
        for i in range(1, len(words)):
            if len(words[i]) > len(words[best_position]):
                best_position = i
        return best_position
    
    print(position_of_longest(["ant", "butterfly", "moth"]))
    print(position_of_longest(["red", "blue", "gold"]))

    Output

    1
    1
    
  57. The calls return 1 and 1. In the second list, blue and gold tie at length 4, so the earlier position wins. This is why an index loop can solve more than the built-in value questions.

  58. Lesson 3: Filter and Combine

    A coach needs a clean list of qualifying scores and a progress line that shows the total after every round. Both jobs build a new list one decision at a time.

  59. Count values that pass a test

    A counter can record how many items pass a condition. It starts at 0 and increases only when the current score reaches the minimum.

  60. def count_qualifiers(scores, minimum):
        count = 0
        for score in scores:
            if score >= minimum:
                count = count + 1
        return count
    
    print(count_qualifiers([8, 13, 11, 6], 10))
    print(count_qualifiers([4, 5, 3], 7))

    Output

    2
    0
    
  61. The calls return 2 and 0. Counting answers how many values pass; filtering keeps the passing values themselves.

  62. Filter into a new list

    To filter, start with an empty result list. Loop over the input, test each item, and call append only inside the if body. This example also practices membership with in.

    On a list, in tests whole-item list membership — “is this value one of the items?” — unlike Unit 09, where in tested character or substring membership inside a string.

  63. def keep_allowed(values, allowed):
        kept = []
        for value in values:
            if value in allowed:
                kept.append(value)
        return kept
    
    print(keep_allowed([4, 9, 2, 9, 7], [2, 4, 7]))
    print(keep_allowed([5, 6], [1, 2, 3]))

    Output

    [4, 2, 7]
    []
    
  64. The calls return [4, 2, 7] and []. The result keeps the input order and includes only values that belong to allowed. Building with an explicit loop makes every filtering decision visible.

  65. Build prefix sums

    A prefix sum is the total so far after each item. Update the running total first, then append that total once per loop trip.

  66. def prefix_sums(numbers):
        totals = []
        running_total = 0
        for number in numbers:
            running_total = running_total + number
            totals.append(running_total)
        return totals
    
    print(prefix_sums([3, 5, 2, 6]))
    print(prefix_sums([-2, 7, -1]))

    Output

    [3, 8, 10, 16]
    [-2, 5, 4]
    
  67. The calls return [3, 8, 10, 16] and [-2, 5, 4]. Each returned item answers, “What is the total through this position?”

  68. Lists inside lists: a grid

    Each inner list can hold one row of a grid. Read a complete row with one index.

  69. grid = [[1, 1, 0], [0, 1, 1]]
    print(grid[1])

    Output

    [0, 1, 1]
    

    Row 1 is [0, 1, 1]. A second index selects a column inside that row.

  70. print(grid[1][0])

    Output

    0
    

    Row 1, column 0 holds 0. Nested loops can turn each numeric row into a text row.

  71. rows = []
    for grid_row in grid:
        row_text = ""
        for value in grid_row:
            if value == 1:
                row_text = row_text + "#"
            else:
                row_text = row_text + "."
        rows.append(row_text)
    print("\n".join(rows))

    Output

    ##.
    .##
    

    The picture prints as ##. and .## on separate lines. "\n".join(rows) makes one string for the whole picture. A board can also store each row as a string.

  72. board = ["#..", ".#.", "..#"]
    print(board[2][2])

    Output

    #
    

    The bottom-right cell is #. To read a board, read its row count, then one row string per line.

  73. Try it
    row_count = int(input("Rows: "))
    board = []
    for i in range(row_count):
        board.append(input("Row: "))
    print(board)

    This input cell builds a list of row strings, ready for board[row][column].

  74. Put it together: keep above-average scores

    This function assumes the list has at least one item. First calculate the average with sum(scores) / len(scores). Then filter every score that is strictly greater than that average into a new list.

  75. def above_average(scores):
        average = sum(scores) / len(scores)
        kept = []
        for score in scores:
            if score > average:
                kept.append(score)
        return kept
    
    print(above_average([10, 16, 12, 18]))
    print(above_average([7, 7, 7]))

    Output

    [16, 18]
    []
    
  76. The first average is 14.0, so the function returns [16, 18]. The second average is 7.0, so no score is strictly above it and the function returns [].

    Put it together: lists keep ordered data, value loops visit items, index loops connect values to positions, and append builds new results. Sorting, finding an extreme, filtering, and prefix sums are different questions built from those same tools.

    • [3, 1, 2] keeps three values in order; scores[0] reads the first one.

    • append grows a list, while a loop can visit each item or its position.

    • scores.sort() changes the list; sorted(scores) makes an ordered copy.

    • To find an extreme, keep the best value or position seen so far.

    • To filter, test each item and append only the ones you want to a new list.

    You can now organize the game club's scores and build a list of qualifying scores.