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
4

5 回答 5

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
于 2016-04-27T01:02:42.340 回答
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]))

您可以直接运行它。

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

于 2016-04-27T00:25:37.360 回答
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

于 2016-04-27T00:28:37.647 回答
0

也许这就是你想要的?

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

如果您想要最小的差异,请返回 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]))
于 2016-04-27T00:36:22.027 回答
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
于 2016-04-27T01:42:41.307 回答