5

How would you find the closest number in comparison to numbers given in a list?

This is what I have tried so far, but it has been unsuccessful:

setted_list = [2, 9, 6, 20, 15]
value_chosen = 17

while True:
    final_value = setted_list[0]
    if setted_list[1] - value_chosen < setted_list[0] - value_chosen:
        final_value = setted_list[1]
    if setted_list[2] - value_chosen < setted_list[1] - value_chosen:
        final_value = setted_list[2]
    if setted_list[3] - value_chosen < setted_list[2] - value_chosen:
        final_value = setted_list[3]
    if setted_list[4] - value_chosen < setted_list[3] - value_chosen:
        final_value = setted_list[4]
print(final_value)

My output is always what is inside the value of setted_list[2]. Where have I gone wrong in my algorithm?

buhtz
  • 10,774
  • 18
  • 76
  • 149

5 Answers5

14

Here's a nice, clean simple one-liner: check this out you'll hopefully learn something new (@ the OP)

print min(setted_list,
          key = lambda x: abs(x-value_chosen))

The min() here does not returned the minimalst value from setted_list. The question What is the minimalst goes to the key= argument. The lambda function create a list() of the difference between each element in setted_list and value_chosen. The minimalst value is not the return value of min() but the index of the minimalst value is used to return the corresponding element in setted_list.

buhtz
  • 10,774
  • 18
  • 76
  • 149
Ryan Burgert
  • 527
  • 5
  • 6
5

The loop while True: never break... you need to find the end point.

maybe you wanted to do something like :

>>> l=max(setted_list)
>>> for i in setted_list:
...     if abs(i-value_chosen)<l:
...             l=abs(i-value_chosen)
...             final_value=i
... 
>>> final_value
15

you can also do something like :

>>> setted_list = [2,9,6,20,15]
>>> value_chosen = 17
>>> min(setted_list, key=lambda x:abs(x-value_chosen))
15
Dadep
  • 2,796
  • 5
  • 27
  • 40
  • 2
    the loop doesn't seem correct to me, you need to initialise a sufficiently large `min_distance` first, compare this with every difference `i-value_chosen` at each iteration and update it every time a shorter distance is found – dvitsios Jul 26 '17 at 20:38
1

If you are too new to understand lambda functions yet,

   minimum = float("inf")
   setted_list = [2, 9, 6, 20, 15]
   value_chosen = 17

   for val in setted_list:
       if abs(val - value_chosen) < minimum:
           final_value = val
           minimum = abs(val - value_chosen)

            
   print final_value
buhtz
  • 10,774
  • 18
  • 76
  • 149
Gingerbread
  • 1,938
  • 8
  • 22
  • 36
  • 1
    you need to update `minimum` every time you find a smaller difference – dvitsios Jul 26 '17 at 20:30
  • @Gingerbread, I understand the code, but I do not understand how the variable "minimum" affects the for loop. – Dhruv Srinivasan Edu Acount Jul 26 '17 at 20:30
  • You're comparing two numbers here. For the first iteration, you need something to which you can compare the absolute difference between the two numbers with. Usually, it's a pretty big number that one chooses in such circumstances if you don't know the range of numbers in your list. So I defined minimum to be infinity. Obviously, the first difference (in this case, |2-17| is definitely going to be lesser than infinity. Now, between infinity and 15, 15 is minimum and you want to know if the difference btw 17 and any other no in the list is smaller, so you update minimum variable everytime. – Gingerbread Jul 26 '17 at 20:38
  • so if I knew the range of my list, I could change the "inf" inside the float() to that number? Also, how does python know that your referring minimum to infinity, when "inf" is in parenthesis? Note: I am a beginner to python, so if the question came of as nooby, I apologize :) – Dhruv Srinivasan Edu Acount Jul 26 '17 at 20:43
  • 1
    Check this link out -> https://stackoverflow.com/questions/7781260/how-can-i-represent-an-infinite-number-in-python – Gingerbread Jul 26 '17 at 20:46
  • If you knew the range and are sure that the elements are not going to change, you can initialize minimum to any number that is greater than the maximum number in the list. – Gingerbread Jul 26 '17 at 20:47
  • The link really helped. Thanks! – Dhruv Srinivasan Edu Acount Jul 26 '17 at 20:48
  • An infinite number is defined like how I did usually. In order to change the minimum variable, you can just assign it to whatever number you have in mind. For ex. `minimum = 10000` – Gingerbread Jul 26 '17 at 20:49
  • Please add more description and explanation to your "answer". In that state it is not an answer. e.g. the third comment (yours) is such an explanation. Add to the answer. – buhtz Aug 31 '21 at 09:21
0
l = [2,9,6,20,15]
val = 17

min_d = max(l) - val
closest_num = -1
for i in l:
    if abs(i - val) < min_d:
        min_d = abs(i-val)
        closest_num = i

print(closest_num)  
#>>> 15
dvitsios
  • 458
  • 2
  • 7
0

Here I use abs() to determine the closest value by subtracting it from the original value

slist = [2, 9, 6, 20, 15]
value = 17

def closest_value(value, iterable):
    storage = []

    for i in iterable:
        storage.append((abs(value - i),i))

    result = min(storage)
    return print(result[1])

closest_value(value, slist)
15
buhtz
  • 10,774
  • 18
  • 76
  • 149
José Garcia
  • 136
  • 9