Home > Mobile >  Find the nearest values above and below a given number in a list
Find the nearest values above and below a given number in a list

Time:02-27

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