I wan to build a function that takes a number from a list of float numbers, and retrieve the nearest values above and below it.
1.1
3.0
6.6
2.2
5.6
4.2
For example, if I pass 4.2, it should retrieve 3.0 and 5.6. How would I achieve this?
CodePudding user response:
Here's the code that does the job:
def upper_and_lower(numbers, target):
sorted_numbers = sorted(numbers)
upper = lower = None
index = sorted_numbers.index(target)
if index < len(sorted_numbers) - 1:
upper = sorted_numbers[index 1]
if index > 0:
lower = sorted_numbers[index - 1]
return upper, lower
numbers = [1.1, 3.0, 6.6, 2.2, 5.6, 4.2]
target = 4.2
print(upper_and_lower(numbers, target))
In the function, the list of numbers first get sorted into sorted_numbers
(ascendingly), so when the index of the given number is index
, the index of the upper number is index 1
and the lower is index - 1
.
In the code snippet, it also checks if the index is out of bound, so if the highest number is entered, 6.6
in this case, the function will output None
as the upper number.
CodePudding user response:
It handles edge scenarios too
lst = [1.1, 3.0, 6.6, 2.2, 5.6, 4.2]
def find_nearest_neighbours(lst, num):
"""
Given a list of numbers, find the two numbers in the list that are closest to the number given
:param lst: the list of numbers
:param num: the number you want to find the nearest neighbours of
:return: The nearest neighbours to the number being searched.
"""
lst.sort()
if num in lst:
if num == lst[0]:
return lst[1]
elif num == lst[-1]:
return lst[-2]
else:
return lst[lst.index(num) - 1], lst[lst.index(num) 1]
else:
return None
print(find_nearest_neighbours(lst, 1.1))
print(find_nearest_neighbours(lst, 4.2))
print(find_nearest_neighbours(lst, 6.6))
print(find_nearest_neighbours(lst, 4.3))
CodePudding user response:
you can solve this problem without any sorting.
import sys
def get_order(num):
lst = [1.1, 3.0, 6.6, 2.2, 5.6, 4.2]
upper = sys.float_info.max
lower = sys.float_info.min
if num not in lst:
print("value does not exist in list")
else:
for val in lst:
if val > num and val < upper:
upper = val
if val < num and val > lower:
lower = val
if upper == sys.float_info.max:
upper = num
if lower == sys.float_info.min:
lower = num
print(f"lower: {lower} , upper: {upper}")
if __name__ == '__main__':
get_order(4.2)
CodePudding user response:
Super fast lookup with bisect:
import bisect
list_ = [
1.1,
3.0,
6.6,
2.2,
5.6,
4.2,
]
sorted_list = sorted(list_[:])
def nearest(list_, key):
idx = bisect.bisect_left(list_, key)
return f"upper: {list_[idx 1]}, lower: {list_[idx-1]}"
if __name__ == "__main__":
print(
nearest(sorted_list, 4.3)
)