删除列表项时发生意外的IndexError [重复]

发布于 2021-01-29 15:02:20

这个问题已经在这里有了答案

如何在迭代时从列表中删除项目? (26个答案)

4年前关闭。

我是Python的初学者。我以前学过其他语言,例如C ++(入门)和JQuery。但是我发现python中的循环非常混乱。

好吧,我想取得一个简单的结果。该程序将循环浏览单词列表,然后将与列表中 两个字母匹配的单词与下一个单词删除:

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。此外,我无法达到预期的效果。你能解释一下吗?

关注者
0
被浏览
91
1 个回答
  • 面试哥
    面试哥 2021-01-29
    为面试而生,有面试问题,就找面试哥。

    您要更改列表的长度,同时循环使用一个达到列表起始长度的范围;从列表中删除一个项目,最后一个索引不再有效。

    移动,因为从当前索引的列表中删除了项目,所以列表的其余索引 转移了 ;索引处的i + 1内容现在位于索引处,i并且循环索引不再有用。

    最后但并非最不重要的一点是,您一直循环到的最后一个索引test,但随后尝试test[i + 1]仍然访问;即使您没有从列表中删除元素,该索引也不存在。

    您可以使用while循环来实现您想做的事情:

    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,在每次循环迭代中针对 新的 长度进行测试,并且只有i在未删除任何元素的情况下,我们才递增。请注意,循环限于长度 减去1,
    因为您要为test[i + 1]每次迭代进行测试。

    注意我用del test[i]; 无需浏览列表即可 再次 搜索要删除的值;如果值在列表中多次出现,但仅应删除 以后的
    实例,这也可能导致细微的错误;例如,['aac', 'foo', 'aac', 'aad']应导致['aac', 'foo', 'aad']
    而不是 ['foo', 'aac', 'aad'],这test.remove(test[i])将导致结果。

    演示:

    >>> 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']
    

    您可以使用列表理解来避免列表缩小的问题:

    >>> [t for i, t in enumerate(test) if i == len(test) - 1 or t[:2] != test[i + 1][:2]]
    ['aac', 'asd', 'msc']
    

    两种方法都只需要在输入列表中循环一次。



知识点
面圈网VIP题库

面圈网VIP题库全新上线,海量真题题库资源。 90大类考试,超10万份考试真题开放下载啦

去下载看看