删除列表项时发生意外的IndexError [英] Unexpected IndexError while removing list items
问题描述
我是Python的初学者.我以前学过其他语言,例如C ++(入门)和JQuery.但是我发现python中的循环非常混乱.
I am a beginner in Python. I have learned other languages before, such as C++ (beginner) and JQuery. But I find the looping in python is quite confusing.
好吧,我想获得一个简单的结果.该程序将遍历单词列表,然后删除与 first 匹配的单词以及列表中的下一个单词的
Well I want to achieve a simple result. The program will loop through a list of words, and then it will remove the words that match with the first two letters with the next word in the list:
test = ['aac', 'aad', 'aac', 'asd', 'msc']
for i in range(len(test)):
if test[i][0:2] == test[i+1][0:2]:
test.remove(test[i])
# This should output only ['aac', 'asd', 'msc']
print test
上面的代码应从列表中删除'aac'
和'aad'
.但实际上,这会引发IndexError
.此外,我无法达到预期的效果.你能解释一下吗?
The code above should remove 'aac'
and 'aad'
from the list. But in reality, this raises an IndexError
. Furthermore, I wasn't able to achieve the desired result. Can you please explain?
推荐答案
您正在更改列表的长度,同时循环使用一个达到列表起始长度的范围;从列表中删除一个项目,最后一个索引不再有效.
You are changing the length of the list while looping over a range that goes up to the starting length of the list; remove one item from the list and the last index is no longer valid.
移动,因为从当前索引的列表中删除了项目,所以列表的其余索引都 shift ;索引i + 1
处的内容现在位于索引i
处,并且循环索引不再有用.
Moveover, because items are removed from the list at the current index, the rest of the list indices shift; what was at index i + 1
is now at index i
and your loop index is no longer useful.
最后但并非最不重要的一点是,您一直循环执行直到test
的最后一个索引,但随后尝试仍然访问test[i + 1]
.即使您没有从列表中删除元素,该索引也不存在.
Last but not least, you are looping until the very last index of test
, but then try to access test[i + 1]
still; that index does not exist even if you were not removing elements from the list.
您可以使用while
循环来实现您想要做的事情:
You could use a while
loop to achieve what you want to do:
test = ['aac', 'aad', 'aac', 'asd', 'msc']
i = 0
while i < len(test) - 1:
if test[i][:2] == test[i+1][:2]:
del test[i]
continue
i += 1
现在i
在每次循环迭代中针对 new 长度进行测试,并且如果没有删除任何元素,我们只会递增i
.请注意,该循环的长度限制为减去1 ,因为您要在每次迭代中测试test[i + 1]
.
Now i
is tested against the new length each loop iteration, and we only increment i
if no element was removed. Note that the loop is limited to the length minus 1 because you want to test for test[i + 1]
each iteration.
请注意,我使用的是del test[i]
;无需浏览列表即可再次搜索要删除的 值;如果值在列表中多次出现,但仅应删除以后实例,则也可能导致细微的错误;例如['aac', 'foo', 'aac', 'aad']
应该导致['aac', 'foo', 'aad']
,而不是 ['foo', 'aac', 'aad']
,这就是test.remove(test[i])
的结果.
Note that I use del test[i]
; no need to scan through the list searching for that the value-to-remove again; this could lead to subtle bugs as well if values appear multiple times in the list but only later instances should be removed; e.g. ['aac', 'foo', 'aac', 'aad']
should result in ['aac', 'foo', 'aad']
, not ['foo', 'aac', 'aad']
, which is what test.remove(test[i])
would result in.
演示:
>>> test = ['aac', 'aad', 'aac', 'asd', 'msc']
>>> i = 0
>>> while i < len(test) - 1:
... if test[i][:2] == test[i+1][:2]:
... del test[i]
... continue
... i += 1
...
>>> test
['aac', 'asd', 'msc']
您可以使用列表理解来避免列表缩小的问题:
You could use a list comprehension to avoid the shrinking list problem:
>>> [t for i, t in enumerate(test) if i == len(test) - 1 or t[:2] != test[i + 1][:2]]
['aac', 'asd', 'msc']
这两种方法都只需要遍历输入列表的一个循环即可.
Both approaches require only one loop through the input list.
这篇关于删除列表项时发生意外的IndexError的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!