迭代列表删除项目,一些项目不会被删除

时间:2010-03-29 21:51:47

标签: python list

我正在尝试将一个列表的内容转移到另一个列表,但它不起作用,我不知道为什么不行。我的代码如下所示:

list1 = [1, 2, 3, 4, 5, 6]
list2 = []

for item in list1:
    list2.append(item)
    list1.remove(item)

但如果我运行它,我的输出看起来像这样:

>>> list1
[2, 4, 6]
>>> list2
[1, 3, 5]

我的问题有三个,我想:为什么会发生这种情况,如何让它发挥作用,我是否会忽略一个非常简单的解决方案,比如“移动”声明或什么?

10 个答案:

答案 0 :(得分:8)

当您在迭代它时,您正在从list1中删除项目。

那是在惹麻烦。

试试这个:

>>> list1 = [1,2,3,4,5,6]
>>> list2 = []
>>> list2 = list1[:] # we copy every element from list1 using a slice
>>> del list1[:] # we delete every element from list1

答案 1 :(得分:8)

原因是你从第一个列表中追加(追加和)删除,因此它会变小。所以迭代器在整个列表可以通过之前停止。

要实现您的目标,请执行以下操作:

list1 = [1, 2, 3, 4, 5, 6]
list2 = []

# You couldn't just make 'list1_copy = list1',
# because this would just copy (share) the reference.
# (i.e. when you change list1_copy, list1 will also change)

# this will make a (new) copy of list1
# so you can happily iterate over it ( without anything getting lost :)
list1_copy = list1[:]

for item in list1_copy:
    list2.append(item)
    list1.remove(item)

list1[start:end:step]slicing syntax:当你离开开始时,它默认为0,当你离开 end 时,它是最高的可能的价值。所以list1 [:]表示其中的所有内容。 (感谢Wallacoloo)

就像一些家伙所说,你也可以使用extend - 对象的list - 方法将一个列表复制到另一个列表,如果这是你的意图。 (但我选择了上面的方法,因为这接近你的方法。)

当你是python的新手时,我会为你提供一些东西:Dive Into Python 3 - 它是免费且简单的。 - 玩得开心!

答案 2 :(得分:4)

基本调试技巧:添加print语句。 (或Python 3中的print函数)

>>> list1= [1, 2, 3, 4, 5, 6]
>>> for item in list1:
...     print item
...     list1.remove(item)
...     print list1
... 
1
[2, 3, 4, 5, 6]
3
[2, 4, 5, 6]
5
[2, 4, 6]

请注意,Python正试图单步执行列表中的位置,但您不断从列表中删除项目,使位置变得毫无意义。

Python从列表中选择位置0处的项目。

然后删除该项目,更改列表。

然后,Python从列表中选择位置1处的项目(似乎跳过项目)

然后删除该项目,更改列表。

然后,Python从列表中选择位置2处的项目(似乎跳过项目)

然后删除该项目,更改列表。

然后,Python会选择位置3处的项目,但是没有这样的项目。所以循环停止了。

答案 3 :(得分:3)

迭代时不应修改列表。这会导致迭代器指向错误的项目。处理完第一个项后,迭代器指向index = 1,但因为你已经删除了一个项,所以下一个项现在是零索引,所以它将被跳过。这就是你只处理所有其他项目的原因。

尝试:

 list2.extend(list1) # This appends all items from list1 to list2.
 del list1[:] # From ChristopheD's post.

答案 4 :(得分:1)

正如ChristopheD所说的那样。

可以这样做:

list1 = [1, 2, 3, 4, 5, 6]
list2 = []

for item in list1:
    list2.append(item)

list1 = []

那清楚的清单1。

修改他/她已更新了自己的帖子。我会把它作为一种轻微的选择。

答案 5 :(得分:1)

使用列表理解:

list2 = [item for item in list1]

将名称list2绑定到与list1相同的对象:

list2 = list1

(请注意,如果您修改list1的内容,list2将相应更改。)

创建list1的副本并将其绑定到名称list2

list2 = list1[:]

在这种情况下,list1和list2是不同的对象。

答案 6 :(得分:1)

请改为尝试:

list1 = [1, 2, 3, 4, 5, 6]
list2 = []

list2.extend(list1)
list1[:] = []

答案 7 :(得分:1)

还有简单的复制功能(如果您的列表中有复杂的对象而不仅仅是整数,则还有深度复制):

from copy import copy

list2 = copy(list1)

如果你解释一下你想要完成什么,你可能会得到一个更合适的答案(除非你只是学习python列表)。

Python中的“变量”只是名称/引用,因此您似乎想要做的破坏性副本似乎有些奇怪。如果您希望list2具有与list1相同的值,您可以这样做:

list2 = list1 # now they are both referring to the same list

如果之后你想使用list1做其他事情,你可以这样做:

list1 = ['A', 'B', 'C']

答案 8 :(得分:1)

正如您在其他答案中所看到的,您正在尝试在迭代时修改列表。这不起作用。将一个列表复制到另一个列表有很多种方法。我做了一些测试,看看每种方法的速度有多快:

>>> timeit.Timer('list2 = list1[:]', 'list1 = range(10**3)').timeit(10**6)
3.9134418964385986

>>> timeit.Timer('list2 = []; list2.extend(list1)', 'list1 = range(10**3)').timeit(10**6)
4.9082601070404053

>>> timeit.Timer('list2 = copy.copy(list1)', 'import copy; list1 = range(10**3)').timeit(10**6)
7.5023419857025146

>>> timeit.Timer('list2 = [i for i in list1]', 'list1 = range(10**3)').timeit(10**6)
95.697894811630249

切片语法最快。它比使用列表理解要快得多。

要清除列表,您可以使用:

del list1[:]

答案 9 :(得分:0)

@potatocubed:给出的许多答案解决了你给出的简单例子(“将list1移动到list2”),但是没有真正解释深层问题的“原因”,即在迭代时修改列表它。研究S.Lott的回答......