【问题标题】:What is wrong with this python list removal loop?这个 python 列表删除循环有什么问题?
【发布时间】:2012-01-08 13:08:18
【问题描述】:

今晚我因为一个很长的计划工作太久了。但我遇到了一个简单的障碍。谁能告诉我为什么这段代码会这样工作?

我有两个列表。我希望 list2 只包含不在 list1 中的数字。 从逻辑上讲,这似乎应该有效。但它根本没有。为什么?

list1 = [1,2,3,4,5,6,7,8]
list2 = [12,15,16,7,34,23,5,23,76,89,9,45,4]


for ch in list2:
    if ch in list1:
         list2.remove(ch)

return list2

不知何故,这会返回: [15、7、5、23、76、9、4]

为什么?

我怎样才能完成我需要的?

【问题讨论】:

    标签: python list loops


    【解决方案1】:

    当您修改您正在迭代的序列时,它会产生意想不到的结果。我会这样做,它利用了快速的set 操作。

    list2 = list(set(list2) - set(list1))
    

    这是否比使用列表解析更快或更慢取决于list1list2 的大小,以及您是否可以将其中一个变为set 作为初始化的一部分,而不是在循环中多次。

    【讨论】:

      【解决方案2】:

      在迭代列表时不要修改它。

      你想要的可以直接用列表推导表达出来:

      list2 = [ch for ch in list2 if ch not in list1]
      

      它更具可读性,并且与带有集合的解决方案不同,它不会从 list2 中删除重复项或更改项目顺序。

      更新:当 list1 很大时,从它创建一个集合实际上会加快速度:

      list2 = [ch for ch in list2 if ch not in set(list1)]
      

      【讨论】:

      • 这是一个很好的观点。虽然你可能想把list1 变成set
      【解决方案3】:

      这是一个有趣的观点。让我解释一下为什么会这样。

      在 python 中使用for a in list 时,python 会依次查看列表的元素 1、元素 2 等。所以它首先查看 12 并将其删除。然后它查看元素 2,除了现在 15 是元素 1 而 16 是元素 2。它删除了 16。所以 15 从未被检查过并留在列表中。然后它同样跳过 7 并删除 34...

      避免这种情况的方法当然是不要在删除元素的同一个列表上进行迭代。您可以复制第二个列表。检查此副本中的成员是否在第一个列表中。如果不是,请将其从第二个列表中删除。我相信已经发布的一些建议对你有用。这就是解释。

      【讨论】:

      • 这也是我的想法,但代码不应该删除 12,因为它不在 list1 中。
      猜你喜欢
      • 1970-01-01
      • 2013-03-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-11-27
      相关资源
      最近更新 更多