Threshold Filter
An easy Python interview practice problem on DataDriven. Write the Python and run it against test cases, with instant feedback.
- Domain
- Python
- Difficulty
- easy
- Seniority
- L3
Problem
Return the metrics from the host snapshot readings whose value meets or exceeds threshold, as a new dict keyed by their original metric names.
Above the line or below it.
Example 1
Input:
readings = {"cpu":85,"mem":40,"net":15,"disk":92}, threshold = 50Output:
{"cpu":85,"disk":92}Example 2
Input:
readings = {"sda":70,"sdb":45,"sdc":80}, threshold = 70Output:
{"sda":70,"sdc":80}Worked solution and explanation
What this really is
This is a value filter over a mapping, dressed up as a metrics check. Two things have to survive the filter: the metric names, and the readings that sit exactly on the cutoff. Almost everyone keeps the names. The answers come apart at the boundary. 'Meets or exceeds' means sda at 70 against a cutoff of 70 stays, and the second example shows exactly that. Type > out of habit and you silently drop every metric pinned at the cutoff, which is usually the one somebody wanted to see.
- Values only
[value for value in readings.values() if value >= threshold]gives[85, 92]. The numbers are right, but nobody can tell which host metric they came from.- Mapping kept
- Iterating
readings.items()keeps each value next to its name, so the result{"cpu": 85, "disk": 92}is still a snapshot a dashboard can read.
Break down the requirements
Step 1: Iterate readings.items(), not the keys
You need the name to key the output and the value to compare. Looping over the keys and then reading readings[metric] also works, but it adds a second lookup per entry and a line the reader has to check.
Step 2: Compare with >=
'Meets or exceeds' is inclusive. Say the boundary out loud before you type it, then check it against the sda example. The negative case behaves the same way: a skew of -1.0 against a cutoff of -1.0 is kept.
Step 3: Return a fresh dict
A comprehension builds a new dict and leaves readings untouched. Deleting entries in place while iterating raises RuntimeError: dictionary changed size during iteration, and even when it runs, it corrupts a snapshot other code still reads.
The solution
def dict_filter(readings, threshold):
return {metric: value for metric, value in readings.items() if value >= threshold}Common follow-up questions
- What if some readings are `None` because a collector timed out? (Tests defensive thinking: `None >= 50` raises `TypeError`, so guard with `value is not None and value >= threshold`.)
- How would you return metric names lowercased? (Tests extending the comprehension with `metric.lower()`, and noticing that two names can collide once they are lowercased.)
- If the snapshot held 100 million metrics, would you still build a dict? (Tests when to yield `(metric, value)` pairs lazily instead, and what is lost by doing so (membership checks, random access).)