You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python通过列表匹配实现列表去重的代码异常原因解析

列表去重代码异常原因分析

问题描述

采用并行列表去重方案:维护新列表t存储已处理元素,遍历原列表时检查目标元素(代码中存在逻辑误用)是否在t中,不在则加入t,在则从原列表删除。代码如下:

# nums = [1,1,2] or [0,0,1,1,1,2,2,3,3,4]

t = []
nums_new = nums
for i in nums:
    if nums[i] not in t:
        t.append(nums[i])
    else:
        nums_new.remove(nums[i])
nums = nums_new
print(nums)

测试nums = [1,1,2]时返回[1,2]看似正常,但测试nums = [0,0,1,1,1,2,2,3,3,4]时输出异常为[0, 1, 2, 2, 3, 3, 4]。

核心错误点

1. 引用赋值而非列表拷贝

nums_new = nums并没有创建新列表,只是让nums_new和nums指向内存中同一个列表。修改nums_new的同时,nums也会同步变化,本质上操作的是同一个列表。

2. 混淆遍历元素与索引

for i in nums中的i是列表的元素值,不是索引,但代码中错误地用nums[i]去取元素。第一个测试用例刚好“歪打正着”:nums=[1,1,2]的元素1对应索引1的元素是1,元素2对应索引2的元素是2,逻辑上刚好匹配;但第二个测试用例中,这种错误逻辑会导致判断的元素并非当前遍历到的i,而是索引为i的元素,完全偏离了去重的初衷。

3. 遍历列表时直接修改列表

在for循环中删除列表元素,会导致列表长度缩短、后续元素前移,而Python的for循环迭代器是在循环开始时生成的,会按初始列表的元素顺序遍历,从而跳过某些前移后的元素,导致重复项未被处理。

具体执行步骤(以nums = [0,0,1,1,1,2,2,3,3,4]为例)

初始状态:nums和nums_new指向同一列表[0,0,1,1,1,2,2,3,3,4],t = []

  1. 第一次循环,i=0(遍历到第一个元素0):
    • 取nums[i] = nums[0] = 0,0不在t中,t变为[0]
  2. 第二次循环,i=0(遍历到第二个元素0):
    • 取nums[i] = nums[0] = 0,0在t中,执行nums_new.remove(0),列表变为[0,1,1,1,2,2,3,3,4](删除第一个出现的0)
  3. 第三次循环,i=1(遍历到第三个元素1):
    • 取nums[i] = nums[1] = 1,1不在t中,t变为[0,1]
  4. 第四次循环,i=1(遍历到第四个元素1):
    • 取nums[i] = nums[1] = 1,1在t中,执行nums_new.remove(1),列表变为[0,1,1,2,2,3,3,4](删除第一个出现的1)
  5. 第五次循环,i=1(遍历到第五个元素1):
    • 取nums[i] = nums[1] = 1,1在t中,执行nums_new.remove(1),列表变为[0,1,2,2,3,3,4](删除第一个出现的1)
  6. 第六次循环,i=2(遍历到第六个元素2):
    • 取nums[i] = nums[2] = 2,2不在t中,t变为[0,1,2]
  7. 第七次循环,i=2(遍历到第七个元素2):
    • 此时列表是[0,1,2,2,3,3,4],取nums[i] = nums[2] = 2,2在t中,执行nums_new.remove(2)时,列表元素前移,迭代器按初始顺序遍历的特性导致后续的2被跳过判断,最终这个2未被删除
  8. 后续循环中,3和4的重复项也因为类似的遍历-修改冲突,出现未被完全删除的情况,最终输出[0, 1, 2, 2, 3, 3, 4]

内容的提问来源于stack exchange,提问作者41 72 6c

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 15:10:33