Python
Algorithms
Programming
Data Structures
Integer Comparison

From list of integers, get number closest to a given value

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

Finding the number closest to a target is a small problem that appears in ranking, recommendations, calibration, and search utilities. The one line solution works for simple cases, but production code also needs deterministic tie rules, empty input handling, and good performance for repeated queries. The right strategy depends on query volume, input size, and whether the list changes between lookups.

One Off Query with min

For a single lookup, min with a key function is concise and correct.

python
1def closest_value(nums, target):
2    return min(nums, key=lambda x: abs(x - target))
3
4
5print(closest_value([10, 3, 27, 18], 20))

This is linear time because every element is inspected once. For one call on a small list, this is usually best for readability.

Add Deterministic Tie Breaking

If two numbers are equally close, define which should win. Without an explicit rule, behavior may be surprising for users and tests.

A common policy is to choose the smaller value.

python
1def closest_value_tie_smallest(nums, target):
2    return min(nums, key=lambda x: (abs(x - target), x))
3
4
5print(closest_value_tie_smallest([4, 6], 5))

If your domain wants the larger value instead, invert the secondary key.

python
def closest_value_tie_largest(nums, target):
    return min(nums, key=lambda x: (abs(x - target), -x))

Document this policy in function naming or docstrings so it is not ambiguous.

Handle Empty Lists Explicitly

min on an empty list raises ValueError. Decide whether your API should raise, return None, or provide a fallback.

python
1def closest_or_none(nums, target):
2    if not nums:
3        return None
4    return min(nums, key=lambda x: (abs(x - target), x))
5
6
7print(closest_or_none([], 12))

Returning None is convenient in some pipelines, but raising is safer when absence is a true error condition.

Optimize Repeated Queries with Sorting and bisect

If you need many target lookups on a fixed list, sorting once and using binary search reduces per query cost.

python
1import bisect
2
3
4class ClosestLookup:
5    def __init__(self, nums):
6        self.arr = sorted(nums)
7
8    def query(self, target):
9        i = bisect.bisect_left(self.arr, target)
10        candidates = []
11        if i < len(self.arr):
12            candidates.append(self.arr[i])
13        if i > 0:
14            candidates.append(self.arr[i - 1])
15        return min(candidates, key=lambda x: (abs(x - target), x))
16
17
18lookup = ClosestLookup([10, 3, 27, 18])
19print(lookup.query(20))
20print(lookup.query(11))

Complexity becomes O(log n) per query after O(n log n) preprocessing.

This optimization only pays off when you reuse the sorted structure. For a single lookup, sorting first is slower than a direct linear scan, because the extra O(n log n) work does not buy you anything.

Return More Than Just the Value

Many use cases need index or distance too. If duplicates exist, index handling should be explicit.

python
1def closest_with_distance(nums, target):
2    value = min(nums, key=lambda x: (abs(x - target), x))
3    return value, abs(value - target)
4
5
6print(closest_with_distance([1, 8, 13, 21], 10))

If index is required, iterate with enumerate and include index in your key tuple.

Consider Numeric Type and Range

Even though the title mentions integers, data pipelines often drift to floats or strings from external sources. Validate input type early if strict integer behavior matters. For huge integers, Python handles big values correctly, but absolute differences may still be expensive for very large lists and repeated calls.

For strict APIs:

python
def validate_int_list(nums):
    if any(not isinstance(x, int) for x in nums):
        raise TypeError("all values must be integers")

If the list is already sorted upstream, preserve that fact instead of rebuilding work inside the helper. A small API choice such as accepting a pre sorted collection can matter when the function becomes part of a larger numerical pipeline.

Common Pitfalls

  • Ignoring tie breaking and getting nondeterministic or surprising outcomes.
  • Using a linear scan for high volume repeated query workloads.
  • Forgetting empty list behavior and triggering runtime exceptions.
  • Returning only value when callers also need distance or index.
  • Skipping input validation when data can contain non integer values.

Summary

  • For one query, min with absolute difference is simple and effective.
  • Define explicit tie policy to keep behavior deterministic.
  • Handle empty inputs intentionally with clear API semantics.
  • For many queries, sort once and use bisect for faster lookups.
  • Return value plus metadata when downstream code needs more context.

Course illustration
Course illustration

All Rights Reserved.