点数列表并找到最近的点麻烦

时间:2016-04-27 00:11:38

标签: python python-2.7 for-loop closest-points

所以我在尝试调试这段代码时遇到了一些麻烦。我有一个数字列表,比如[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

5 个答案:

答案 0 :(得分: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]))

您可以直接运行它。

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

答案 1 :(得分:0)

您可以使用itertools首先提供列表中元素的所有组合2,然后计算它们的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

答案 2 :(得分:0)

也许那就是你想要的?

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

如果你想要最小的diffrence返回diff。

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

答案 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

答案 4 :(得分: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