SDD15 — Standard Algorithms with Arrays of Records
- I can adapt linear search, minimum, maximum, and count-occurrences to work on an array of records
- I can explain why these algorithms must compare a specific field of each record, rather than the record as a whole
- I can write a linear search that compares a named field (e.g.
.name) of each record to a target - I can adapt the minimum/maximum algorithms to compare a named field (e.g.
.stock,.price) of each record - I can adapt count-occurrences to count how many records satisfy a condition on a named field
- I can explain that all four algorithms keep the same overall structure from SDD13/14 — only the comparison changes from a bare value to
record.field
stockLevels = [30, 45, 20, 15, 60, 18], what is the minimum value?for loop that checks every element, unlike linear search?Key vocabulary
.stock), rather than comparing the whole record.stock < 20), not just an exact match.The same four algorithms, one field at a time
What changes, and what doesn't
SDD13 and SDD14 built linear search, minimum, maximum, and count-occurrences against plain 1D arrays of bare values. This lesson re-runs all four algorithms against the tuck shop's itemRecords array of Item @dataclass records (SDD6–12) — and the good news is that the algorithm's overall structure never changes. What changes is exactly one thing: every comparison that previously read a bare array element, such as array[i], now reads one specific named field of a record instead, such as records[i].stock. The loop, the running variables, and the logic are all identical to SDD13/14 — only what's being compared is different.
Linear search on a record field
Rather than searching an array of plain names for a match, linear search on records compares one field — typically .name — of each record to the target, e.g. records[index].name == target. The rest of the algorithm (the found flag, the incrementing index, the -1 sentinel for "not found") is completely unchanged from SDD13.
Minimum and maximum on a record field
Instead of comparing bare numbers, the minimum/maximum algorithms now compare a chosen numeric field of each record — for example, finding the record with the lowest stock (comparing records[i].stock) or the record with the highest price (comparing records[i].price). Critically, what's usually wanted here isn't the smallest number in isolation, but which item has it — so these algorithms typically track the index of the current best record, not just the field value itself, so the whole matching record can still be retrieved afterwards.
Count-occurrences as a condition, not just equality
SDD14's count-occurrences checked for an exact match (array[i] == target). Applied to records, this same "running counter, check every element" shape works equally well for a condition rather than strict equality — for example, counting how many items have stock < 20 (a reorder-warning count), simply by swapping == for < in the comparison. The algorithm's shape is unchanged; only the comparison operator and what's being compared (a field, not a bare value) are different.
Why this lesson matters beyond just "more practice"
It would be easy to treat this lesson as simply repeating SDD13/14 with slightly different data, but the real point is narrower and more useful than that: recognising exactly which single line of an already-known, already-tested algorithm needs to change to make it work on a new data structure, rather than treating records as requiring a completely new algorithm to be designed from scratch. This is precisely the kind of transferable skill the SQA assignment (Task 1, SDD7–SDD12's parameter passing and file handling combined with SDD13–15's algorithms) rewards — recognising a standard pattern and adapting it, rather than reinventing logic that already exists and is already known to work correctly.
Worked examples
itemRecords array of Item records (Chocolate, Crisps, Juice, Flapjack, Sweets, Muffin):
def linearSearchRecords(records, target):
index = 0
found = False
while index < len(records) and not found:
if records[index].name == target:
found = True
else:
index = index + 1
if found:
return index
else:
return -1
result = linearSearchRecords(itemRecords, "Flapjack")linearSearch: the only change is array[index] == target becoming records[index].name == target.result is 3 — confirmed by an actual Python run. Searching for "Kale", which does not exist, correctly returns -1.def findMinStockRecord(records):
smallestIndex = 0
for i in range(1, len(records)):
if records[i].stock < records[smallestIndex].stock:
smallestIndex = i
return smallestIndex
minIndex = findMinStockRecord(itemRecords)smallestIndex — the position of the best record so far — is tracked, not the stock value itself, so the whole matching Item record can still be retrieved via records[smallestIndex] afterwards.minIndex is 3, and itemRecords[3] is Item(name='Flapjack', price=110, stock=15) — confirmed by an actual Python run.def findMaxPriceRecord(records):
largestIndex = 0
for i in range(1, len(records)):
if records[i].price > records[largestIndex].price:
largestIndex = i
return largestIndex
maxIndex = findMaxPriceRecord(itemRecords).price instead of .stock, and > instead of < — exactly the same relationship SDD14 established between its own minimum and maximum algorithms.maxIndex is 5, and itemRecords[5] is Item(name='Muffin', price=120, stock=18) — confirmed by an actual Python run.def countLowStock(records, threshold):
count = 0
for i in range(len(records)):
if records[i].stock < threshold:
count = count + 1
return count
result = countLowStock(itemRecords, 20)< 20.result is 2 — confirmed by an actual Python run. This is the same "running counter, check every element" shape as SDD14's countOccurrences, just with a condition (<) in place of strict equality (==).findMinStockRecord pattern to instead write findMaxStockRecord, finding the index of the record with the highest stock level. What index and item does it find in itemRecords?
- Comparing the whole record instead of one field.
records[i] < records[smallestIndex]is not a valid comparison between twoItemobjects — a specific field, such as.stock, must be named explicitly. - Tracking the field value instead of the index. If only the smallest stock number itself is stored, rather than its index, the matching record's other fields (name, price) can no longer be retrieved afterwards.
- Forgetting the algorithm's shape hasn't changed. Pupils sometimes rewrite the whole algorithm from scratch for records, when only the comparison line needs to change from SDD13/14's version.
- Assuming count-occurrences only checks for equality. Swapping
==for a condition like<or>is a valid, common variation — the algorithm still counts how many elements satisfy the test, just not strict equality. - Using the wrong field for the wrong question. "Which item is cheapest?" needs
.price; "which item needs restocking soonest?" needs.stock— always check exactly which field a question is asking about.
When adapting a standard algorithm to work on records, state explicitly which field is being compared, and whether the algorithm is tracking an index (so the whole record can be retrieved) or a bare value. Examiners will accept SDD13/14's algorithms almost unchanged here — the marks are for correctly identifying which one line needs to change, not for rewriting the whole algorithm.
Task Set A — Core questions
itemRecords array, at what index is the record with .name equal to "Flapjack"?.stock value?.price value?stock < 20?if records[i] < records[smallestIndex]: to find the minimum-stock record. What is wrong with this?countLowStock that takes an array of Item records and a threshold, and returns how many records have .stock below the threshold.def countLowStock(records, threshold):
count = 0
for i in range(len(records)):
if records[i].stock < threshold:
count = count + 1
return count
countOccurrences (checking for an exact match) and this lesson's countLowStock (checking a condition). (3 marks)linearSearchRecords(itemRecords, "Kale") return, given "Kale" does not appear in the array?Task Set B — Extension
stock < 20) — combining a condition with a minimum-finding algorithm.findMinStockRecord or countLowStock should specifically include.Higher Computing Science → Software Design & Development → SDD15
Single period, though content-dense (four algorithms re-run) — if the single P3 slot proves tight in practice, consider trimming Task Set A to 8 questions rather than 10, or moving Question 9/10 to a follow-up starter next lesson.
This is the pedagogical payoff lesson combining SDD6–12 (records) with SDD13/14 (algorithms) — deliberately reuses the exact itemRecords six-item array established across SDD6–12 (including the Muffin record added in SDD12), for maximum continuity.
Suggested timing: 5 min warm-up + vocab · 15 min notes · 20 min examples 1–4 · 5 min "now you try" · remainder Task Set A; Task Set B as homework/extension.
Key misconception: pupils sometimes try to rewrite each algorithm from scratch for records, rather than recognising only the comparison line changes from SDD13/14 — worth explicitly showing the SDD13/14 code and the SDD15 code side by side to make the single-line diff visible.
This completes the algorithm-specification strand (SDD13–15) and the SQA content map's Implementation strand in full. SDD16 (Testing) begins the Testing/Evaluation portion of the course.
SQA command words covered: explain, write code.