遍历列表时如何正确移除元素?索引异常问题排查与解决
遍历列表移除元素时索引偏移的问题解决
你的问题根源在于遍历原列表的同时修改它:当你用enumerate遍历se_names时,每执行一次pop(i),列表长度就会减1,后续元素会向前偏移一位。举个例子,salt在索引8,删除它之后,sugar会移到索引8的位置,但此时循环的索引已经走到9了,而新的列表长度只有9(索引0-8),所以9超出范围,sugar根本没被遍历到,自然不会被删除。
下面给你几种可行的解决方法:
方法1:遍历列表的副本
遍历原列表的拷贝,这样原列表的修改不会影响遍历的索引顺序:
#list to match fi_names = ["apple", "orange", "pepper", "orange", "cake", "tree", "tree", "leaf"] #list to modify to match the first one se_names = ["apple", "orange", "pepper", "orange", "cake", "tree", "tree", "leaf", "salt", "sugar"] x_names = list( set(se_names) - set(fi_names) ) # 遍历se_names的副本 for i, e in enumerate(se_names.copy()): if e in x_names: se_names.pop(i) print(se_names)
方法2:反向遍历列表
从列表末尾开始往前遍历,删除元素不会影响未处理的前面元素的索引:
#list to match fi_names = ["apple", "orange", "pepper", "orange", "cake", "tree", "tree", "leaf"] #list to modify to match the first one se_names = ["apple", "orange", "pepper", "orange", "cake", "tree", "tree", "leaf", "salt", "sugar"] x_names = list( set(se_names) - set(fi_names) ) # 从最后一个索引反向遍历到0 for i in range(len(se_names)-1, -1, -1): if se_names[i] in x_names: se_names.pop(i) print(se_names)
方法3:生成新列表(推荐)
直接用列表推导式生成符合要求的新列表,这种方式更简洁直观,也避免了修改原列表带来的索引问题:
#list to match fi_names = ["apple", "orange", "pepper", "orange", "cake", "tree", "tree", "leaf"] #list to modify to match the first one se_names = ["apple", "orange", "pepper", "orange", "cake", "tree", "tree", "leaf", "salt", "sugar"] # 直接保留fi_names中存在的元素 se_names = [e for e in se_names if e in fi_names] print(se_names)
这种方法甚至不需要先计算x_names,一步到位得到你想要的结果。
另外提一句:你用set求差集的方式没问题,但如果列表中有需要保留的重复元素(比如fi_names里的两个orange),set会自动去重,但这里不影响你的需求——因为你只是要移除不在fi_names里的元素,所以没问题。
内容的提问来源于stack exchange,提问作者Sheep
相关产品推荐
相关产品推荐

