清除列表中指定字符串时触发IndexError错误,求代码问题排查
老哥,咱们来拆解下你这段代码为啥会触发IndexError: list index out of range,还有几个隐藏的坑:
核心问题拆解
无限递归的致命问题:你在函数末尾又调用了
clearOutPut(array),这会让函数无限自我调用,直到Python触发递归深度报错,而且这完全是多余的——你的循环已经在尝试处理列表了,根本不需要递归。固定索引范围导致越界:你一开始就把
size设为len(array)-1,但每次执行array.pop(x)都会让列表长度变短。举个例子:初始列表有5个元素,size=4,当你删掉1个元素后,列表只剩4个元素,最大索引变成3,但循环还是会跑到x=4,这时候自然就找不到这个索引了,直接抛出越界错误。正向遍历删除会跳过元素:当你删除
array[x]后,x位置后面的所有元素都会往前挪一位,比如原来的array[x+1]会变成新的array[x],但下一次循环x会加1,直接跳过了这个刚挪过来的元素,导致有些包含"test"的项没被清理掉。匹配逻辑的漏洞:
array[x].find('test') > 0这个判断会漏掉以"test"开头的字符串(比如"test123"),因为find在匹配到字符串开头时返回0,不满足>0的条件。正确的判断应该是array[x].find('test') != -1,或者更直观的'test' in array[x]。
修复后的几种实现方案
方案1:反向遍历(推荐,原地修改列表)
从后往前遍历索引,这样删除元素不会影响前面还没遍历到的元素,也不会出现索引越界:
def clearOutPut(array): # 从最后一个索引开始,倒着遍历到0 for x in range(len(array)-1, -1, -1): if 'test' in array[x]: array.pop(x) return array
方案2:列表推导式(更Pythonic,生成新列表)
如果不需要修改原列表,直接生成一个不包含目标字符串的新列表,完全避开索引问题:
def clearOutPut(array): return [item for item in array if 'test' not in item]
方案3:while循环遍历(原地修改的另一种方式)
用while循环控制索引,只有当没删除元素时才递增索引,避免跳过元素:
def clearOutPut(array): x = 0 while x < len(array): if 'test' in array[x]: array.pop(x) else: x += 1 return array
内容的提问来源于stack exchange,提问作者High Five

