查看: 219|回复: 0

Python列表去重5种实现方法:保序、性能与不可哈希处理

[复制链接]
发表于 2 小时前 | 显示全部楼层 |阅读模式
Python 列表去重看起来简单,实际选型主要看两个条件:一是结果是否必须保持元素首次出现的顺序,二是列表里的元素是否可哈希。像 [[1, 2], [1, 2], [3]] 这种嵌套列表就属于不可哈希元素,直接交给 set 或 dict 会报错。下面按这两个条件,把 5 种解法逐一说明,并给出函数实现、调用示例和复杂度判断。

1. dict.fromkeys:保序去重的首选

从 Python 3.7 开始,dict 会保留键的插入顺序,因此可以用 dict.fromkeys(lst) 先得到去重后的字典,再用 list() 取出所有键。字典键本身唯一,这一过程的时间复杂度为 O(n),写法也最简洁。
  1. def remove_duplicates_ordered(lst):
  2.     return list(dict.fromkeys(lst))
  3. my_list = [3, 1, 4, 1, 5, 9, 2, 6, 5]
  4. print(remove_duplicates_ordered(my_list))
  5. # 输出: [3, 1, 4, 5, 9, 2, 6]
复制代码

函数只做两步:dict.fromkeys 创建以列表元素为键的字典,list 把字典键转回列表。因为 dict 在 3.7 及之后保证插入顺序,所以结果会按元素第一次出现的顺序排列。日常开发中如果元素可哈希且要求保序,这是优先选择。

2. set 集合:最快但不保序

如果完全不关心顺序,只要求去重,set 是最短路径。集合天然不允许重复元素,转成 list 后即可使用。它的时间复杂度同样为 O(n),但不保证原始顺序,实际输出顺序由哈希决定。
  1. def remove_duplicates_unordered(lst):
  2.     return list(set(lst))
  3. my_list = [3, 1, 4, 1, 5, 9, 2, 6, 5]
  4. print(remove_duplicates_unordered(my_list))
  5. # 输出顺序不确定,例如 [1, 2, 3, 4, 5, 6, 9]
复制代码

这个方法代码量最少,适合只想要去重结果、不依赖顺序的场景。如果后续逻辑依赖元素先后次序,就不要用 set 方案。

3. 辅助集合 seen:保序且可插入自定义逻辑

需要保序、又想在去重过程中加入自定义判断时,可以用辅助集合 seen 配合结果列表。遍历原列表,元素第一次出现时追加到 result,同时写入 seen。由于集合查询是 O(1),整体仍为 O(n),并且写法兼容较老的 Python 版本。
  1. def remove_duplicates_seen(lst):
  2.     seen = set()
  3.     result = []
  4.     for item in lst:
  5.         if item not in seen:
  6.             seen.add(item)
  7.             result.append(item)
  8.     return result
复制代码

这种方法的价值在于控制力更强。比如可以在 if 条件里加过滤空值、大小写归一、类型转换等处理,再去决定是否加入结果列表。

4. 纯列表遍历:处理不可哈希元素

当列表元素本身不可哈希时,例如嵌套列表 [[1, 2], [1, 2], [3]],set 和 dict 方案都会报错。此时只能退回到纯列表遍历,用 in 检查结果列表中是否已经存在相同元素。因为每次 in 都要扫描 result,时间复杂度为 O(n²),数据量大时性能下降明显,仅适合小规模数据。
  1. def remove_duplicates_unhashable(lst):
  2.     result = []
  3.     for item in lst:
  4.         if item not in result:
  5.             result.append(item)
  6.     return result
  7. nested = [[1, 2], [1, 2], [3]]
  8. print(remove_duplicates_unhashable(nested))
  9. # 输出: [[1, 2], [3]]
复制代码

选择这个方案前,先确认元素确实不可哈希。如果只是普通数字、字符串、元组,仍然应该用基于哈希的方法。

5. Pandas:数据清洗场景的 drop_duplicates

如果项目已经用 Pandas 做数据清洗,可以直接把列表转成 Series,再调用 drop_duplicates()。该方法默认保留首次出现的顺序,并且对大规模数据、混合类型以及包含 NaN 的场景支持较好。代价是要引入 Pandas 依赖,不适合只为列表去重而专门安装。
  1. import pandas as pd
  2. def remove_duplicates_pandas(lst):
  3.     return pd.Series(lst).drop_duplicates().tolist()
复制代码

这段函数把列表包装成 Series,调用 drop_duplicates 去重,最后用 tolist 转回 Python 列表。适合数据分析流程中顺带完成去重。

选型建议与复杂度对照

把 5 种方案放在一起,可以按下面思路决策:

- 日常开发、要求保序、元素可哈希:dict.fromkeys(),O(n)。
- 完全不关心顺序、只追求速度:set(),O(n)。
- 需要保序并插入自定义过滤或转换逻辑,或兼容非常老的 Python:辅助集合 seen,O(n)。
- 元素不可哈希,例如嵌套列表:纯列表遍历,O(n²),仅小规模使用。
- 已经在使用 Pandas、做数据清洗、数据量大或包含 NaN:pd.Series().drop_duplicates(),默认保留首次出现顺序。

原文给出的总结同样清晰:日常首选方法 1,即 dict.fromkeys;不在乎顺序只求快,用方法 2 的 set;遇到嵌套列表报错,用方法 4 的纯列表遍历。理解保序需求和可哈希边界,就能在这几种写法之间快速选对方案。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

指导单位

江苏省公安厅

江苏省通信管理局

浙江省台州刑侦支队

DEFCON GROUP 86025

Hacking Group 021A

旗下站点

态势感知中心

应急响应中心

红盟安全

联系我们

官方QQ群:112851260

官方邮箱:security#ihonker.org(#改成@)

官方核心成员

关注微信公众号

Archiver|手机版|小黑屋| ( 沪ICP备2021026908号 )

GMT+8, 2026-9-23 12:02 , Processed in 0.021231 second(s), 18 queries , Gzip On, Redis On.

Powered by ihonker.com

Copyright © 2015-现在.

  • 返回顶部