2016-04-27 75 views
0

所以我遇到了一些麻烦,试图调试这段代码。我有一个数字列表,例如[4,5,7,3,5,2,3],我需要找到两个最接近的点,所以在这种情况下,3和3因为它们的差值为零。但是,它不会返回正确的输出。如果一个数字不在列表中重复出现,但它在某个数字出现多次时不起作用。点列表并找到最近的点故障

def closest1(num_list): 
     if len(num_list) < 2: 
      return (None, None) 
     else: 
      diff = max(num_list), min(num_list) 
      for element in num_list: 
       for sec_element in num_list: 
        if sec_element == element: 
         continue 
        if abs(sec_element - element) < abs(diff[0] - diff[1]): 
         diff = sec_element, element 
     return diff 
+0

你试过列表进行排序,第一 – Keatinge

+0

'[X在num_list x如果num_list.count(X)> 1]'将返回重复。如果没有,您可以继续对列表进行排序并找出差异。 – jDo

+0

还有另一对距离为0(5,5)的列表。有没有一种方法可以选择(3,3)或者没关系? – sal

回答

0

我认为你的问题是,当你找到相同的数字,你运行一个continue语句。在那个地方,条件应该是每个数字的位置。如果位置相同,则应该跳过该数字,但如果位置不同并且数字相同则是有效的情况。

在另一方面,您不需要查找既不是最小值也不需要查找最大值,然后计算最长距离。从前两个数字的差异开始,以获得更好的表现。

下面是代码的固定:

def closest1(num_list): 
     if len(num_list) < 2: 
      return (None, None) 
     else: 
      num1 = num_list[0] 
      num2 = num_list[1] 
      diff = abs(num1 - num2) 
      if diff == 0: # Better case ever! You compute almost nothing! :D 
       return num1, num2 
      # enumerates(list) gives you the pair (position, value) for each item of the list. 
      for p1, element in enumerate(num_list): 
       for p2, sec_element in enumerate(num_list): 
        if p1 == p2: # Compare positions, not values ;) 
         continue # Here is the big fix! 
        if abs(sec_element - element) < abs(diff): 
         diff = sec_element - element 
         num1 = element 
         num2 = sec_element 
         if diff == 0: # Great case! Don't have to compute all the list! :) 
          return num1, num2 
     return num1, num2 

if __name__ == '__main__': 
    print("Should be 0,1 and it is %s,%s" % closest1(range(10))) 
    print("Should be 4,4 and it is %s,%s" % closest1([4,5,6,7,8,6,4,2])) 

您可以直接运行它。

注意:此代码仅用于教育目的,有更多高性能的方法。

0

您可以使用itertools首先提供列表中所有元素的组合,然后计算它们的distance。最后一步是只返回该名单的min,所以你的功能可能会被改写为:

import itertools 
def closest1(num_list): 
    return min([(abs(x[0]-x[1]),x) for x in itertools.combinations(num_list, 2)]) 

返回(0,(3,3)) 见这里的行动:https://eval.in/560204

0

也许那就是你想要的?

如果你想要最接近的数字,我认为这是解决方案。

如果你想要最小差异返回差异。

def closest(num_list): 
    tmp = (None, None) 
    diff = max(num_list) - min(num_list) 
    for i in range(len(num_list)): 
     for j in range(len(num_list)): 
      if i != j and diff >= abs(num_list[i] - num_list[j]) : 
       tmp = (num_list[i], num_list[j]) 
       diff = abs(num_list[i] - num_list[j]) 
    return tmp 
print(closest([4,5,7,3,5,2,3])) 
0

只有一个循环是必要的,如果您排序第一:

def closest1(num_list): 
    num_list = sorted(num_list) 
    diff = num_list[0] - num_list[-1] 
    diff_dict = {"num1":diff, "num2":diff, "diff":diff} 
    for pos, val in enumerate(num_list[:-1]): 
     diff = abs(num_list[pos+1] - val) 
     if diff < diff_dict["diff"]: 
      diff_dict = {"num1":num_list[pos+1], "num2":val, "diff":diff} 
    return diff_dict 
+0

是的,我们应该使用嵌套for循环这个功能...第二个功能使用排序 – PythonSOS

+0

@PythonSOS好吧,我忘记这些问题有时是功课。嵌套循环经常在真实代码中避免,但如果这是必需的,我认为Svaris或Hamlett的解决方案是迄今为止最好的。 – jDo

0

必须使用range迭代这样的条件if sec_element == element:不会混淆拖的比较与相同的值不同的元素元素与自身的比较。

此外,您不必遍历第二个循环中的所有元素。这里是你的代码的变化:

def closest1(num_list): 
    if len(num_list) < 2: 
     return (None, None) 

    a, b = num_list[0], num_list[1] 
    diff = b - a 
    for i in range(len(num_list)): 
     for j in range(i): 
      new_diff = num_list[i] - num_list[j] 
      if abs(new_diff) < abs(diff): 
       diff = new_diff 
       a, b = num_list[i], num_list[j] 
    return a, b