Sorting and Unique
Unique Values
Collect the distinct values from an 8-element list that contains repeats. A
dict accumulates each value as a key (ignoring duplicates), then sorted
produces the final ordered list. The trace shows seen filling up — its size
staying at 6 even though 8 elements are processed.
By hand
Loop over values writing each v as a key in seen (dict assignment is
idempotent for duplicate keys). After the loop, sorted(seen.keys()) gives
the unique values in ascending order.
naive.py
Replay: real traced execution (multi-file project)
values = [3, 1, 4, 1, 5, 9, 3, 2]
seen = {}
for v in values:
seen[v] = True
unique = sorted(seen.keys())
print('RESULT:', unique)
values ← [3, 1, 4, 1, 5, 9, 3, 2]
1values = [3, 1, 4, 1, 5, 9, 3, 2]2seen = {}values this step[3, 1, 4, 1, 5, 9, 3, 2]valuesseen ← {}
1values = [3, 1, 4, 1, 5, 9, 3, 2]2seen = {}3for v in values:values this step{}seenv ← 3
2seen = {}3for v in values:4 seen[v] = Truevalues this step3vseen ← {3: True}
3for v in values:4 seen[v] = True5unique = sorted(seen.keys())values this step{} → {3: True}seenv ← 1
2seen = {}3for v in values:4 seen[v] = Truevalues this step3 → 1vseen ← {3: True, 1: True}
3for v in values:4 seen[v] = True5unique = sorted(seen.keys())values this step{3: True} → {3: True, 1: True}seenv ← 4
2seen = {}3for v in values:4 seen[v] = Truevalues this step1 → 4vseen ← {3: True, 1: True, 4: True}
3for v in values:4 seen[v] = True5unique = sorted(seen.keys())values this step{3: True, 1: True} → {3: True, 1: True, 4: True}seenv ← 1
2seen = {}3for v in values:4 seen[v] = Truevalues this step4 → 1vseen[v] = True
3for v in values:4 seen[v] = True5unique = sorted(seen.keys())v ← 5
2seen = {}3for v in values:4 seen[v] = Truevalues this step1 → 5vseen ← {3: True, 1: True, 4: True, 5: True}
3for v in values:4 seen[v] = True5unique = sorted(seen.keys())values this step{3: True, 1: True, 4: True} → {3: True, 1: True, 4: True, 5: True}seenv ← 9
2seen = {}3for v in values:4 seen[v] = Truevalues this step5 → 9vseen ← {3: True, 1: True, 4: True, 5: True, 9: True}
3for v in values:4 seen[v] = True5unique = sorted(seen.keys())values this step{3: True, 1: True, 4: True, 5: True} → {3: True, 1: True, 4: True, 5: True, 9: True}seenv ← 3
2seen = {}3for v in values:4 seen[v] = Truevalues this step9 → 3vseen[v] = True
3for v in values:4 seen[v] = True5unique = sorted(seen.keys())v ← 2
2seen = {}3for v in values:4 seen[v] = Truevalues this step3 → 2vseen ← {3: True, 1: True, 4: True, 5: True, 9: True, 2: True}
3for v in values:4 seen[v] = True5unique = sorted(seen.keys())values this step{3: True, 1: True, 4: True, 5: True, 9: True} → {3: True, 1: True, 4: True, 5: True, 9: True, 2: True}seenfor v in values:
2seen = {}3for v in values:4 seen[v] = Trueunique ← [1, 2, 3, 4, 5, 9]
4 seen[v] = True5unique = sorted(seen.keys())6print('RESULT:', unique)values this step[1, 2, 3, 4, 5, 9]uniquestdout ← RESULT: [1, 2, 3, 4, 5, 9]
5unique = sorted(seen.keys())6print('RESULT:', unique)values this stepRESULT: [1, 2, 3, 4, 5, 9]stdout
With NumPy
np.unique(a) returns a sorted array of unique values in one call. The output
shape (6,) is smaller than the input shape (8,) — unique reduces the
array.
library.py
import numpy as np
values = [3, 1, 4, 1, 5, 9, 3, 2]
a = np.array(values)
result = np.unique(a)
print('a: shape:', a.shape, 'dtype:', a.dtype, 'values:', a.tolist())
print('result: shape:', result.shape, 'dtype:', result.dtype, 'values:', result.tolist())
print('RESULT:', result.tolist())
a: shape: (8,) dtype: int64 values: [3, 1, 4, 1, 5, 9, 3, 2]
result: shape: (6,) dtype: int64 values: [1, 2, 3, 4, 5, 9]
RESULT: [1, 2, 3, 4, 5, 9]
Implementation notes
np.uniquealways sorts its output — the sorted order is part of the contract, not a side effect. The naivesorted(seen.keys())call at the print boundary matches this so both RESULT lines agree.np.unique(a, return_counts=True)also returns the count of each unique value, useful for frequency analysis.- The Python equivalent of unique is
sorted(set(values)). The dict approach here keeps the seen-key pattern visible in the trace (unlikeset, which has no meaningful step-by-step membership story for the tracer). - Shape, dtype, and values are shown explicitly here because
ndarray.__repr__output varies with NumPy version and print options.