Explain Codes LogoExplain Codes Logo

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

python
performance
best-practices
dataframe
Anton ShumikhinbyAnton Shumikhin·Feb 7, 2025
TLDR

To find the nearest value to a target in an integer list, wield the power of min() function. Combine it with lambda to reduce the absolute diff with the target. Essentially, do this:

# Reduce the target to zero, or at least try! closest = min(numbers, key=lambda x: abs(x - target_value))

Minimize the diff in a list numbers and a target_value:

# We have a list of wannabes numbers = [4, 1, 88, 44, 3] target_value = 5 # One of you is the one print(min(numbers, key=lambda x: abs(x - target_value))) # Output: 4

Aha! It's 4! The number that's playing hard to get with target_value.

Sorted list performance boost

If your program resembles a neurotic squirrel, constantly querying a list for the closest value, try a different approach. Sort the list once and use search algorithms sparingly.

In a sorted list, the bisect module jumps into save the day with its O(log n) surreptitious search solution. bisect_left points the flashlight at the right position for the target_value in the sorted list. You can then play a game of 'who's the closest' with the nearest neighbors:

import bisect # Sort or perish numbers.sort() target_value = 5 # Where do you fit in, target_value? index = bisect.bisect_left(numbers, target_value) # Let's settle this over a min() closest = min(numbers[max(0, index-1): index+2], key=lambda x: abs(x - target_value))

You do this, and it's a game of numbers on massive, sorted lists and multiple queries.

Lambda variable assignment and dict support

Assign the lambda to a variable, aka, give lambda a name! It helps with code readability and allows you to use it again. And again.

# Original recipe def closest_number(numbers, target): return min(numbers, key=lambda x: abs(x - target)) # Use it again, Sam print(closest_number([10, 20, 30], 25)) # Output: 20

Fun fact: this method cooperates with dictionaries, too! You just wrap min() around dict.keys():

numbers = {4: 'a', 1: 'b', 88: 'c', 44: 'd'} target_value = 5 # Not keys to a kingdom, but close enough closest_key = min(numbers.keys(), key=lambda k: abs(k - target_value))

Edge case blues

To make your solution robust, sing the blues, or rather, look at your edge cases. An empty ensemble, a one-man band, or multiple numbers that played the main part equally well...Make sure to "cover" your tracks:

numbers = [] target_value = 5 # It's lonely in here... closest = min(numbers, key=lambda x: abs(x - target_value)) if numbers else None

If multiple values are tripping over themselves to be the closest, min() gives the first one a chance. Not very diplomatic, but it's a start!

Advanced methods and considerations

Nailing performance trade-offs

If you're wrestling with a large dataset, weigh your options between sorting and using bisect against running min() every single time. min() has an O(n) complexity for each call, but if your list hasn't been touched in a while, sort it first for O(n log n) complexity and use bisect for some O(log n) action.

Parallel processing for massive lists

If you've been handed a biblical-size list, you might want to split it into smaller pieces or 'chunks'. Try multiprocessing or concurrent.futures modules. They work like little elves, crunching the numbers behind the scenes and splitting the work between each other.

Real-world applications

Everything from finding average temperature on Mars to predicting the next best cryptocurrency, finding the closest number is never not cool. You can use it in k-nearest neighbor algorithms or in time-series data to find the moment that aligns with your guilt for not calling your mother back.