【问题标题】:Python: removing items from inner and outer for loop iterators [duplicate]Python:从内部和外部for循环迭代器中删除项目[重复]
【发布时间】:2013-02-15 16:16:47
【问题描述】:

这段代码有潜在危险吗?会不会弄乱内部和外部的迭代?

for a in listA:
            for b in listB: 
                if [... something...]:
                    ... something else...
                    listA.remove(a)
                    listB.remove(b)
                    break

【问题讨论】:

  • 是的,是的:它可能不会像你想要的那样运行。见stackoverflow.com/questions/1207406/…
  • 也许可以试试这个:for b in listb[:]: 它只会复制列表,您可以从原始列表中删除。
  • 是的,这听起来比必须通过列表推导来完成所有事情要好得多。我在上面的“...其他东西”中做了很多事情,压缩上面链接中建议的所有内容会有点麻烦。

标签: python list for-loop iterator


【解决方案1】:

这段代码有潜在危险吗?依靠。在迭代序列时减小序列的大小会产生意想不到的行为。

考虑这个例子

listA = [1,2,3,4]

>>> for a in listA:
    listA.remove(a)
    print a

因为,在删除项目时,超出它的所有项目都被推向左侧,您打算迭代的项目将自动移动到下一个元素

第一次迭代:

    listA = [1,2,3,4]
             ^
             |
_____________|

    listA.remove(a)


    listA = [2,3,4]
             ^
             |
_____________|


    print a
    (outputs) 1

第二次迭代:

    listA = [2,3,4]
               ^
               |
_______________|

    listA.remove(a)

    listA = [2,4]
               ^
               |
_______________|


    print a
    (outputs) 3

第三次迭代:

    listA = [2,4]
                 ^
                 |
_________________|

(Exits the Loop)

【讨论】:

  • 哦,所以我实际上是在跳过项目,这正是我所经历的行为。非常感谢您的解释。
【解决方案2】:

更改被迭代的序列通常是 Python 中的反模式。虽然您可以在特定情况下围绕它跳舞,但最好看看您是否可以构建一个仅包含您需要的项目的新列表(或 dict)。

【讨论】:

  • 其实我会同时删除ab,然后调用break,这让我跳出了内循环并移动到listA中的下一个元素。
  • 啊,错过了休息时间。你是对的,我会编辑我的答案(一般原则仍然适用)。
【解决方案3】:

我同意 jknupp - 删除列表中的项目可能比创建新项目更昂贵。然而,另一个技巧是倒着做:

>>> l = range(5)
>>> for a in reversed(l):
...     print a
...     l.remove(a)
... 
4
3
2
1
0

【讨论】:

  • 嗯。会反向创建列表的本地副本吗?否则我看不出区别。
  • 不, reversed() 创建一个反向迭代器。它的名字有点误导,但至少它不是太冗长。通过向后迭代,您已经传递了将被 remove() 替换的所有元素。
猜你喜欢
  • 2013-06-07
  • 1970-01-01
  • 2019-07-10
  • 1970-01-01
  • 2015-11-23
  • 2011-10-18
  • 1970-01-01
  • 1970-01-01
  • 2019-03-14
相关资源
最近更新 更多