我在尝试删除时遇到了一个有趣且令人费解的情况 列表中的所有空字符串。我第一次写下面的代码。
lst=['###','','@@@','','$$$','','','%%%','','&&&']
print "len:",len(lst)
iteration=1
for item in lst:
print iteration,":",lst,":",len(lst),":","'%s'"%item
if item!='':
pass
else:
lst.remove(item)
iteration+=1
它产生以下输出:
len: 10
1 : ['###', '', '@@@', '', '$$$', '', '', '%%%', '', '&&&'] : 10 : '###'
2 : ['###', '', '@@@', '', '$$$', '', '', '%%%', '', '&&&'] : 10 : ''
3 : ['###', '@@@', '', '$$$', '', '', '%%%', '', '&&&'] : 9 : ''
4 : ['###', '@@@', '$$$', '', '', '%%%', '', '&&&'] : 8 : ''
5 : ['###', '@@@', '$$$', '', '%%%', '', '&&&'] : 7 : '%%%'
6 : ['###', '@@@', '$$$', '', '%%%', '', '&&&'] : 7 : ''
注意:代码不能正常工作。这里有一些空字符串
输出。
后来我找到了更好的方法:
列表理解:[x for x in lst if x!='']
或创建一个新列表并将非空字符串复制到它,这发生了
比上面的代码更有效,因为它不涉及转移
每次从列表中删除元素时的位置。
但是我对上面代码的输出有一些疑问。
第一个问题是,为什么循环不运行十次(迭代次数打开
因为列表的原始长度是十。
其次,如果你看最右边的列,你会发现它不会打印
打印@@@
字符串。完全跳过它!我的理论是in
运算符
是一个索引的糖(最有可能),所以即使列表的长度发生变化
指数继续增加一。这可以解释为什么在第三次迭代
由于i
为@@@
,lst[2]
的值为空字符串,而不是''
。
使用in运算符时是否需要了解一些内容?
答案 0 :(得分:2)
任何时候你在迭代过程中删除东西时都会得到奇怪的结果。如果迭代切片[:]
,字符串将不再消失
for item in lst[:]:
创建一个迭代的副本,以便您可以操作列表的元素而不影响迭代
this帖子描述了在迭代时修改列表时会发生什么。
答案 1 :(得分:0)
在内部,迭代列表使用索引。每次通过循环时,此索引递增1,并用于检索所需的元素。如果在迭代时删除一个元素,一个新元素将“移动到”你正在查看的插槽中,然后循环的下一个迭代将查看下一个,所以首先移动的元素永远不会被查看在
一些解决方案包括:
lst[:] = (item for item if item != "")
这是最快的,因为它可以避免在删除时多次移动项目。reversed()
以相反顺序迭代列表,这样您就只能“移动”您已经看过的项目。在您的情况下,您实际上不需要遍历列表。您只想从中删除空字符串。所以第四个选择是删除空字符串,直到没有更多!
try:
while True:
lst.remove('') # deletes first empty string
except ValueError: # no more empty strings
pass