Python3根据嵌套列表内层值删除元素时触发索引越界问题
错误原因
你遇到的IndexError本质是遍历列表的同时原地删除列表元素导致的索引错位:
- 循环启动时
range(len(persons))会基于列表初始长度生成固定的索引序列,不会随着列表长度变化动态调整 - 每执行一次
del persons[i],被删位置之后的所有元素都会向前移动一位,列表实际长度减1 - 当循环走到初始计算的靠后索引时,列表实际长度已经小于当前索引值,访问不存在的位置就会触发索引越界。
额外注意两个细节问题:
- 你贴的初始示例数据里
['p2', 10, 88]和后面的['p3', 39, 66]之间缺少逗号,直接运行会先触发语法错误,需要补上 - 你描述里写的
L1[x][3] == 88是按从1开始的序号计数,Python列表索引从0开始,第三个元素对应的索引值为2,你原有代码里取persons[i][2]的索引写法是正确的。
正确实现方案
优先推荐用列表推导式生成符合要求的新列表,逻辑清晰无副作用,不会出现索引问题。
方案1:列表推导式(推荐)
如果需求是删除内层列表索引2位置值为88的子列表,代码如下:
persons = [['p1', 12, 45], ['p2', 10, 88], ['p3', 39, 66], ['p4', 34, 88], ['p5', 20, 16]] # 保留所有内层列表第3个元素(索引2)不等于88的项 persons = [p for p in persons if p[2] != 88]
对应你原来判断persons[i][2] > longivity就删除的逻辑,只需要把判断条件反过来即可:
persons = [p for p in persons if p[2] <= longivity]
运行后得到的persons为[['p1', 12, 45], ['p3', 39, 66], ['p5', 20, 16]],符合删除要求。
方案2:倒序遍历原地删除
如果你必须原地修改原列表不生成新对象,可以从列表末尾往开头遍历,这样删除元素不会影响还未遍历到的元素的索引:
# 从最后一个元素的索引开始,倒着遍历到索引0 for i in range(len(persons)-1, -1, -1): if persons[i][2] == 88: # 替换成 if persons[i][2] > longivity 即可适配你的原判断逻辑 del persons[i]
不推荐用正向遍历加偏移量计数的写法,容易写错边界条件,维护成本高。
内容的提问来源于stack exchange,提问作者BigD
相关产品推荐
相关产品推荐

