Batch Records
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
- L3
Problem
A support engineer is replaying records into a downstream API that rejects any call carrying more than n of them, so the records have to go out as consecutive batches of at most n, in their original order.
Too many at once. Break them into groups.
Example 1
Input:
records = [1,2,3,4,5], n = 2
Output:
[[1,2],[3,4],[5]]
Example 2
Input:
records = [1,2,3], n = 1
Output:
[[1],[2],[3]]
Worked solution and explanation
What this really is
This is fixed-size partitioning wearing a batch-processing costume. The skill being probed: can you cut a sequence into consecutive groups of at most n without losing anything at the edges? Anyone can write a loop. The trap is deciding how many batches there are up front, computing the count with floor division and taking records[i*n:(i+1)*n]. Get that wrong and the ragged tail silently vanishes: [1,2,3,4,5] with n=2 loses [5], and [10,20,30] with n=5 returns [] instead of [[10,20,30]], because 3 // 5 == 0. Records disappear at the end of the replay and nothing errors.
- Count then divide (drops the tail)
for i in range(len(records) // n): out.append(records[i*n:(i+1)*n]). On[1,2,3,4,5]with n=2,5 // 2 == 2, so you emit two batches and the leftover[5]never gets a turn. The count is a lie the moment the length isn't a multiple of n.- Stride and slice (uniform)
for i in range(0, len(records), n): out.append(records[i:i+n]). You never compute a count. You walk start indices0, n, 2n, ...and let the slice decide how many records it actually gets, so the short final batch falls out for free.
How to build it
Step 1: Stride the start indices with range(0, len(records), n)
The three-arg range gives you 0, n, 2n, ... and stops before len(records). The start of each batch is the only thing you track, so there is no per-batch counter to get out of sync.
Step 2: Slice records[i:i + n] for each start
Python slicing clamps silently: records[i:i+n] returns whatever remains when fewer than n records are left, so the last batch is naturally shorter with zero special-casing. The same expression covers n larger than the list (one full-length batch) and the empty list (the loop never runs).
Step 3: Append each slice and return
Collect every slice into batches and return it. There are no length checks, no remainder math and no if guarding the tail, because the edge cases the interviewer is waiting for are already handled by the loop bounds and the slice.
def chunk_list(records, n):
batches = []
for i in range(0, len(records), n):
batch = records[i:i + n]
batches.append(batch)
return batchesCommon follow-up questions
- What if `records` is a lazy generator instead of a list, and you can't call `len()` on it? (Slicing and range-step both need random access; this pushes you to `itertools.islice` in a loop, consuming n at a time until exhausted.)
- What changes if n can be `0` or negative? (`range(0, len(records), 0)` raises `ValueError`; tests whether you validate n before striding rather than after records are lost.)
- How would you split into a fixed number of near-equal batches rather than a fixed size? (Flips the knob from batch size to batch count and forces you to distribute the remainder, as in `numpy.array_split`.)