One Step Behind
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
You're aligning a stream of sensor readings so each one can sit beside the reading that came just before it. Return a list the same length as the input, where each slot carries its predecessor's value.
What came before this row?
Example 1
Input:
values = [10,20,15,30,25]
Output:
[null,10,20,15,30]
Example 2
Input:
values = [5]
Output:
[null]
Worked solution and explanation
The real problem
Underneath the lag framing this is a boundary problem, not a shifting problem. Carrying each value into the next slot is the easy part; the tell is what you seed the output with and where its length comes from. The shortcut almost everyone reaches for seeds result = [None] and copies from index 1, which reads fine until an empty list arrives and you hand back [None] instead of []. That one phantom row breaks the same-length promise every downstream column-align step leans on.
Walk it
Step 1: Carry the previous value forward
Keep a single prev variable. Before you read each value, the answer for the current slot is whatever you saw last time, which starts as None. Append prev, then update it to the current value. The first append naturally lands None because nothing came before.
Step 2: Let the input drive the length
The output grows one slot per input element, so its length is the input's length by construction. That is the whole fix: never seed a slot the input did not ask for. Empty input walks zero times and returns an empty list; a single element appends exactly one None.
The solution
def lag(values):
result = []
prev = None
for value in values:
result.append(prev)
prev = value
return resultLength comes from the loop, so empty in gives empty out.
- Seed-and-copy (breaks on empty)
result = [None]then looprange(1, len(values)). Correct on every non-empty input, but an empty list returns[None], a length-1 result where the contract demands length 0.- Carry-forward (length from input)
- Start
result = []and append one slot per element. The length is whatever the input's length is, so the empty case falls out as[]with no special-casing.
Common follow-up questions
- How would you generalize this to a lag of k positions? (Tests prepending k Nones and taking values[:-k], while still deriving the length from the input.)
- How would you implement a lead (forward-looking) version? (Tests the mirror operation: each slot carries the NEXT value, with None filling the final slot.)
- How does this relate to SQL's LAG() window function? (Tests mapping LAG(col, 1) OVER (ORDER BY ...) onto this exact carry-forward pattern.)