1. Records and arrays of records

Callum has sold a booking system to a paddleboard hire in Portobello. Forty boards, each with a name, a size, a price per hour, and whether it's out on the water. Jess suggested four lists. Priya suggested one list of forty boards, where each board carries its own four facts. "Lists drift apart," she said. "A board doesn't."

Who's who: Quayside Code is a small software studio in Leith. Priya is the lead developer, Callum the founder who sells projects before they exist, and Jess an S6 pupil with a Saturday job.

A record in Python

A record groups the fields that describe one thing. In reference language it looks like this:

RECORD Board IS {STRING name, CHARACTER size, REAL rate, BOOLEAN isOut}

Python has no RECORD keyword. The usual way is a class whose fields are set up with a starting value of the right type. Run it:

class Board: def __init__(self): self.name = "" self.size = "" self.rate = 0.0 self.isOut = False board = Board() board.name = "Kestrel" board.rate = 12.5 print(board.name, board.rate, board.isOut)

Board() makes one new board record. board.name is the name field of that record. The fields' starting values ("", 0.0, False) show their types: string, real and Boolean.

An array of records

In reference language, an array of 40 boards is DECLARE boards AS ARRAY OF Board INITIALLY [] * 40. In Python, make 40 separate records:

class Board: def __init__(self): self.name = "" self.rate = 0.0 boards = [Board() for index in range(40)] boards[0].name = "Kestrel" boards[12].name = "Puffin" boards[12].rate = 15.0 print(len(boards), boards[0].name, boards[12].name, boards[12].rate)

To reach one field of one record, choose the record by its index, then the field: boards[12].rate.

A trap: one record forty times

This looks like it makes three boards. Predict what it displays, then run it.

class Board: def __init__(self): self.name = "" boards = [Board()] * 3 boards[0].name = "Kestrel" print(boards[0].name, boards[1].name, boards[2].name)

[Board()] * 3 makes one record and puts it in the list three times, so changing one changes "all" of them. Use [Board() for index in range(3)] to make three separate records. In the exam, the * n version gains only one of the two marks for declaring the array.

Exercises

A hillwalking app stores each hill's name (a string), height in metres (an integer) and region (a string). Write a class Hill for this record, then declare hills: an array of 5 separate Hill records. The lines that use them are already written: do not change them.

Copy the shape of the Board class: one line per field, each with a starting value of the right type. Then hills = [Hill() for index in range(5)].

The old program kept the boards in two parallel arrays. Copy them into boards, an array of 4 Board records, using a fixed loop: element index of each array goes into the fields of boards[index]. Then, in a second loop, display each board as name: rate, for example Kestrel: 12.5.

boards[index].name = names[index] inside a for loop. To display, join with + and use str() for the rate.

Using the array of records, display the name of every board whose rate is more than 12, one per line, in array order. Use a loop over the array and boards[index].rate.

for index in range(len(boards)): then if boards[index].rate > 12: and print the name field.

This class takes the fields' values when each record is made: Board("Kestrel", 12.5). Both ways are fine in the exam. What matters is that each record has every field, and the array holds separate records.

In the exam

A record question asked every year: write the record structure (1 mark for the structure with its name, 1 for all the fields with suitable types), then declare an array of them (1 mark for the right size, 1 for using your record type). You can write it in reference language or as a Python class. Later parts use array[index].field; an answer with parallel arrays instead keeps the algorithm marks but loses the marks for the names.

Next: lesson 2: the standard algorithms on an array of records.