为什么我的for循环跳过了列表中的一个元素?

7
我有一个整数列表,我正在通过 for 循环来发现其中两个元素的和是否等于另一个变量 t。所以如果 t 等于 10,并且我有一个整数列表:l = [1,2,3,4,5,8,9],那么函数应该打印出所有不同的数字组合 (1,9)(2,8)
我觉得我已经接近成功了,但是当我使用 .pop() 函数时,列表中会发生奇怪的事情。下面的代码被用来展示需要计算的所有数字组合,但是列表中每隔一个元素就会被跳过。
l = [1,2,5,8,13,15,26,38]
c = 10
for i in l:
    first = i
    l.pop(0)
    for x in l:
        second = x
        print(first,second)

这是输出结果:

1 2
1 5
1 8
1 13
1 15
1 26
1 38
5 5
5 8
5 13
5 15
5 26
5 38
13 8
13 13
13 15
13 26
13 38
26 13
26 15
26 26
26 38

注意,281538被跳过了。 我使用l.pop(),这样第二个for循环就不会使用原始值,下一次迭代就可以继续迭代列表中的下一个元素。

10
我不是Python专家,但我可以告诉你,在其他面向对象的语言中,从循环中修改迭代器或被迭代的集合通常被认为是一个相当糟糕的想法。我的第一个怀疑会停留在这里。你从列表中弹出(pop)一个元素,然后尝试在幕后引用list[1]... 但是list[1]现在已经是5了,而不是你期望的2,因为你已经修改了列表。 - David Hoelzer
1
我认为@DavidHoelzer给出了正确的答案。 - Flying_Banana
@AndrewRushton:这是一个相当人为的限制...如果你向后迭代列表,你可以安全地从正在迭代的列表中删除元素,尽管在列表的副本上迭代更安全。顺便说一句,.pop(0)相当低效,因为它强制列表移动所有剩余的列表元素以填补空缺。 - PM 2Ring
2个回答

12
您试图做的事情不会起作用,因为您在迭代列表时修改了它。假设当前“指针”指向第一个元素。现在您弹出第一个元素,因此指针位于第二个元素。但是当循环前进时,指针将移动到第三个元素,并跳过第二个元素。
看起来您想从列表中找出组合。您可以尝试以下几种方法:
- 最接近您当前方法的方式:使用while循环而不是for循环。
while l:
    first = l.pop(0)
    for second in l:
        print(first, second)
  • 或者,您可以仅迭代索引而不是列表本身:

    for i in range(len(l)):
        for k in range(i+1, len(l)):
            print(l[i], l[k])
    
  • 或者只需使用itertools.combinations

  • import itertools
    for first, second in itertools.combinations(l, 2):
        print(first, second)
    

    不过,你可以做得更好。由于你正在寻找一对数字,它们的总和等于某个目标数字,只需从目标数字中减去第一个数字即可得到第二个数字,并查看该第二个数字是否在数字列表中。使用一个set可以使这种查找在常数时间内完成,将整体时间复杂度从O(n²)降至O(n)。

    numbers = set([1,2,5,8,13,15,26,38])
    target = 10
    for first in numbers:
        second = target - first
        if second > first and second in numbers:
            print(first, second)
    

    0

    你需要选择另一种方法。在使用for循环迭代列表时,不允许从中删除元素。


    网页内容由stack overflow 提供, 点击上面的
    可以查看英文原文,
    原文链接