Python 如果在迭代列表时从列表中删除元素,为什么会跳过它?
我试过这个:Python 如果在迭代列表时从列表中删除元素,为什么会跳过它?,python,list,python-2.7,Python,List,Python 2.7,我试过这个: list = [[1], [2], [], [4], [5], [], [], [], [9]] for e in list: if e == []: list.remove(e) 然后我得到了 >>> list [[1], [2], [4], [5], [], [9]] 发生什么事了 for e in list: if e == []: list.remove(e) 在这种情况下,当e为空列表时,该特定值将从
list = [[1], [2], [], [4], [5], [], [], [], [9]]
for e in list:
if e == []:
list.remove(e)
然后我得到了
>>> list
[[1], [2], [4], [5], [], [9]]
发生什么事了
for e in list:
if e == []:
list.remove(e)
在这种情况下,当e
为空列表时,该特定值将从列表中删除。因此,列表中的下一个元素将成为当前元素。在下一次迭代中,下一个元素取自列表。由于实际的下一个元素已向后移动,因此将采用下一个实际的下一个元素。因此,如果存在多个连续匹配,则有可能跳过元素
在您的情况下,假设e
位于[]
后面的[2]
[[1], [2], [], [4], [5], [], [], [], [9]]
^
因为它是一个空列表,所以它将被删除,列表将变为空
[[1], [2], [4], [5], [], [], [], [9]]
^
在下一次迭代中,将拾取下一个元素,因此
[[1], [2], [4], [5], [], [], [], [9]]
^
在本例中,我们无声地跳过了[4]
。但是,由于它是在输出中预期的,所以没有任何区别。但是考虑<<代码> [COD] > <代码> > [5 ] < /代码>,
[[1], [2], [4], [5], [], [], [], [9]]
^
这将被删除,因此列表如下所示
[[1], [2], [4], [5], [], [], [9]]
^
>>> [e for e in list if e]
[[1], [2], [4], [5], [9]]
现在,在下一次迭代中,e
将引用下一个元素,即
[[1], [2], [4], [5], [], [], [9]]
^
因此,当前的空列表被删除,[9]
成为当前元素。这就是跳过其中一个空列表的方式
注意:底线是,在迭代容器时,不要从容器中删除项目
解决方案1:
最常见的技术是使用正在迭代的列表的副本,因为迭代和实际列表将在循环中修改。比如说,
for e in list[:]: # `list[:]` is a shallow copy of `list`
if e == []:
list.remove(e)
解决方案2:(首选方法)
使用列表理解和过滤条件创建一个新列表,如下所示
[[1], [2], [4], [5], [], [], [9]]
^
>>> [e for e in list if e]
[[1], [2], [4], [5], [9]]
注意消除空列表的方式。Python中的空列表被视为假值。因此,
if e
只有在e
中至少有一个元素时才会计算为Truthy。独立于语言的解决方案:向后迭代
l = [[1], [2], [], [4], [5], [], [], [], [9]]
for e in reversed(l):
if e == []:
l.remove(e)
内置函数
过滤器
也提供此功能。作为列表理解的替代方法,您可以使用过滤器(无,列表)
@nelfin True,但在Python@nelfin列表理解比过滤器
和映射
方法更快,并且在可能的情况下,应该优先选择,在这种情况下,列表理解实际上较慢:~$python-m timeit-s'import random;l=[[]if random.random()<0.5 else[1]表示uuu在范围内(1000000)]“[x表示在l if x中的x]”
10个循环,每个循环最好3:44.9毫秒
~$python-m timeit-s'导入随机;l=[]if random.random()<0.5 else[1]表示“范围内(1000000)]”过滤器(无,l)
10个循环,每个循环最好3:25.7毫秒
@nelfin这两个测试不是在两个不同的随机列表上运行吗?可能重复