删除列表项时发生意外的IndexError [英] Unexpected IndexError while removing list items

查看:58
本文介绍了删除列表项时发生意外的IndexError的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆