The Quiet Drift
A medium Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.
- Domain
- Python
- Difficulty
- medium
- Seniority
- L4
- Asked in
- Amazon
Problem
Two nightly imports of the same ledger should hold identical records keyed by id_field, but the upstream systems drift and rows diverge. Reconcile the two lists into four id-ordered buckets: ids only in source_a, ids only in source_b, ids in both with identical records, and ids in both whose records differ, reporting for that last bucket which non-id fields differ and each source's value, treating a field absent from one source as None there.
Two versions of the same truth.
Example
Input:
source_a = [{"id":1,"amount":100,"status":"posted"},{"id":2,"amount":200,"status":"posted"},{"id":3,"amount":300,"status":"pending"}], source_b = [{"id":1,"amount":100,"status":"posted"},{"id":2,"note":"adjusted","amount":205,"status":"posted"},{"id":4,"amount":400,"status":"posted"}], id_field = "id"Output:
{"only_a":[3],"only_b":[4],"matches":[1],"mismatches":[{"id":2,"differences":{"note":{"a":null,"b":"adjusted"},"amount":{"a":200,"b":205}}}]}Worked solution and explanation
What this problem really is
Strip the ledger costume and this is a membership classification wearing a field-level diff on its back. Everyone gets the easy half: index both sources by id, then set-difference and intersection to split ids into only_a, only_b, and both. The half that separates candidates is the diff on the 'both' bucket. The trap is quietly diffing only the keys of the source_a record. Do that and a field that lives only in source_b never gets looked at, so a record that genuinely drifted gets filed under 'matches'. Get it wrong and a real data-quality problem ships clean, with no alert.
Break down the requirements
Step 1: Index both sources by id
Build map_a and map_b: dicts keyed by record[id_field] so id lookups are O(1). The output has four keys: only_a, only_b, matches, mismatches.
Step 2: Membership classification with set operations
Use Python set operations on the two id sets: only_a = ids_a - ids_b, only_b = ids_b - ids_a, both = ids_a & ids_b. Sort the first two before returning.
Step 3: Field-level diff for matched ids
For each id in both, compare the two records field by field over the UNION of their non-id keys. If every non-id field is equal, the id goes in matches. Otherwise, build {field: {'a': a_val, 'b': b_val}} for each differing field and append {'id': id, 'differences': ...} to mismatches. The union is what saves you from the one-directional-diff trap: in the visible example id 2 carries note only in source_b, so it surfaces as {'a': None, 'b': 'adjusted'}.
Step 4: Sort and assemble
Return the four keys with only_a, only_b, matches sorted by id, and mismatches sorted by id. Iterating the intersection in sorted order gives you sorted matches and mismatches for free.
The solution
def reconcile(source_a: list[dict], source_b: list[dict], id_field: str) -> dict:
map_a = {r[id_field]: r for r in source_a}
map_b = {r[id_field]: r for r in source_b}
ids_a = set(map_a)
ids_b = set(map_b)
only_a = sorted(ids_a - ids_b)
only_b = sorted(ids_b - ids_a)
matches = []
mismatches = []
for rid in sorted(ids_a & ids_b):
a, b = map_a[rid], map_b[rid]
fields = (set(a) | set(b)) - {id_field}
diffs = {}
for f in fields:
if a.get(f) != b.get(f):
diffs[f] = {'a': a.get(f), 'b': b.get(f)}
if diffs:
mismatches.append({'id': rid, 'differences': diffs})
else:
matches.append(rid)
return {
'only_a': only_a,
'only_b': only_b,
'matches': matches,
'mismatches': mismatches,
}Common follow-up questions
- How would you present the diff in a human-readable report? (Tests formatting diffs with old/new values in a table layout.)
- What if records had nested structures? (Tests recursive field comparison.)
- How would this scale to millions of records? (Tests streaming reconciliation with sorted merge or database-side comparison.)
- What if the ID field were not unique in one of the lists? (Tests handling multi-valued mappings or flagging the anomaly.)