函数中for循环未遍历整个列表,提前终止迭代问题排查
原地移除奇数次出现元素时循环提前终止的原因分析
原代码与问题现象
oldlist = [42, 72, 32, 4, 94, 82, 67, 67, 89, 89, 89, 89, 5, 90, 5, 5] def removeodds(thing): for i in reversed(thing): icount = thing.count(i) if icount % 2 > 0: while i in thing: thing.remove(i) return thing newlist = removeodds(oldlist) print(newlist)
功能需求:移除列表中出现奇数次的元素,仅保留出现偶数次的元素
实际输出:[42, 72, 32, 4, 94, 82, 67, 67, 89, 89, 89, 89, 90]
预期输出:[67, 67, 89, 89, 89, 89]
可行的修改方案
oldlist = [42, 42, 72, 42, 72, 4, 94, 82, 67, 67, 89, 89, 89, 89, 5, 90, 5, 5] def removeodds(thing): for i in thing[::-1]: icount = thing.count(i) if icount % 2 > 0: while i in thing: thing.remove(i) return thing newlist = removeodds(oldlist) print(newlist)
核心原因拆解
reversed(thing)返回的是绑定原列表的实时迭代器,它的遍历范围会跟着原列表的动态修改变化。当你在循环里执行remove操作删除元素时,原列表长度会缩短,迭代器会提前耗尽,导致前面那些需要处理的元素(比如42、72这类出现奇数次的元素)根本没机会进入循环。- 原场景中,处理元素
5时会把所有5都删掉,原列表长度从16骤减到13,此时reversed迭代器已经没有后续元素可以遍历,循环直接终止,剩下的90、42等元素都没被检查。 - 而
thing[::-1]是先生成原列表的完整副本,循环遍历的是这个固定不变的副本。不管原列表后续怎么删元素,循环都会遍历完初始的所有元素,确保每个元素都被检查是否需要移除。
内容的提问来源于stack exchange,提问作者Get Over Here
相关产品推荐
相关产品推荐

