Stable deduplication keeps the first occurrence of each key and preserves the input order of those first occurrences.
Python exercise: retain first-seen order while rejecting duplicate IDs
Operation contract
The import preview accepts a bounded list of short ASCII receipt IDs. It returns unique IDs in first-seen order and a separate duplicate count. The first duplicate is not silently deleted from the source list; the function creates new output. This is useful for previewing a batch, but it does not grant exactly-once processing of external effects.
Failure and ownership boundary
Set iteration order is not the requested output order, so the algorithm uses a set only for membership and a list for presentation. For a durable import, duplicate rules also need a stored unique key and transaction policy. Python SQLite job project: reject conflicting replays by request identity, Python exercise: reconcile duplicate receipt counts without losing multiplicity and Python dictionaries: insertion order and duplicate-key replacement show distinct contracts.
Working program
def first_seen(receipt_ids):
if type(receipt_ids) is not list or len(receipt_ids) > 100:
raise ValueError("batch cap")
if any(type(identifier) is not str or len(identifier) != 3 or identifier[0] != "R" or any(char not in "0123456789" for char in identifier[1:]) for identifier in receipt_ids):
raise ValueError("ASCII receipt ID")
seen = set()
ordered = []
duplicates = 0
for identifier in receipt_ids:
if identifier in seen:
duplicates += 1
else:
seen.add(identifier)
ordered.append(identifier)
return ordered, duplicates
batch = ["R42", "R41", "R42", "R43", "R41"]
print(first_seen(batch))
print("input kept:", batch[0])Output
(['R42', 'R41', 'R43'], 2)
input kept: R42Costs and limits
Expected O(n) membership work and O(u) retained keys plus O(u) output references for u unique IDs; worst-case collision behavior is not constant. The 100-record gate bounds this exercise. Durable deduplication needs persistent state beyond this process.
Common Mistakes
- A set alone discards the requested first-seen sequence.
- In-memory deduplication is not exactly-once delivery.
Connected lessons
Python SQLite job project: reject conflicting replays by request identity, Python exercise: reconcile duplicate receipt counts without losing multiplicity, Python dictionaries: insertion order and duplicate-key replacement.
