您正在更改列表的长度,同时在一个范围内循环,该范围一直到列表的起始长度;从列表中删除一项,最后一个索引不再有效。
移动,因为项目从当前索引处的列表中删除,列表索引的其余部分移位;索引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 在每次循环迭代中都针对 new 长度进行测试,如果没有删除任何元素,我们只会增加 i。请注意,循环的长度限制为 minus 1,因为您想在每次迭代时测试 test[i + 1]。
注意我使用del test[i];无需扫描列表来搜索要删除的值再次;如果值在列表中出现多次但只有 later 实例应该被删除,这也可能导致细微的错误;例如['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']
这两种方法都只需要一个循环遍历输入列表。