'Find the nearest values above and below a given number in a list

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?



Solution 1:[1]

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))

Solution 2:[2]

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)

Solution 3:[3]

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)
    )

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Parvesh Kumar
Solution 2
Solution 3