Python使用反向迭代器删除列表重复项结果顺序不符预期原因求解
问题原因
你代码的问题核心出在list.remove()方法的行为:list.remove(x)会永久删除列表中第一个和x相等的元素,而非你当前遍历到的那个元素。
你用反向遍历的逻辑本来是想避免正向遍历删元素导致的索引偏移问题,但你调用remove的时候删的是列表头部的重复项,而不是你当前正在遍历的尾部重复项。
拿你的输入列表举例:
初始列表:[2, 4, 5, 6, 9, 4, 0, 8, 2, 4]
反向遍历的第一个元素是末尾的4,此时count(4)=3>1,你调用remove(4)会删掉列表里第一个出现的4(索引1的位置),而不是你当前遍历到的末尾的4。
后续遍历到重复的2时,同样会删掉列表开头第一个出现的2,而不是当前遍历到的靠后的2。
最终你保留下来的都是每个元素最后一次出现的实例,所以顺序就和你预期的「保留首次出现顺序」完全相反,得到了[5, 6, 9, 0, 8, 2, 4]的结果。
另外你原代码中调用list.count()每次都要遍历全列表,整体时间复杂度为O(n²),列表长度较大时效率会非常低。
可行的去重实现(保留元素首次出现顺序)
方案1:Python 3.7+ 最简写法
利用Python 3.7+版本字典默认保留插入顺序的特性,一行即可实现:
numbers = [2, 4, 5, 6, 9, 4, 0, 8, 2, 4] res = list(dict.fromkeys(numbers)) print(res) # 输出 [2, 4, 5, 6, 9, 0, 8]
方案2:兼容所有版本的通用写法
用集合记录已经出现过的元素,正向遍历一次即可,时间复杂度O(n),执行效率更高:
numbers = [2, 4, 5, 6, 9, 4, 0, 8, 2, 4] seen = set() res = [] for num in numbers: if num not in seen: seen.add(num) res.append(num) print(res) # 输出 [2, 4, 5, 6, 9, 0, 8]
内容的提问来源于stack exchange,提问作者CharlieH
相关产品推荐
相关产品推荐

