7人参与 • 2025-12-12 • Python
列表去重是python开发的高频需求,但多数开发者只停留在list(set(lst))的表层用法。殊不知在数据量放大到10万、100万级时,不同方案的效率差异可达100倍以上——曾遇到过同事用列表推导式处理100万条日志去重,耗时12分钟,换成set后仅需0.3秒。
| 方法 | 底层实现 | 时间复杂度 | 核心依赖 |
|---|---|---|---|
set(lst) | 哈希表(hash table) | o(n) | python内置类型,c语言实现 |
dict.fromkeys(lst) | 字典键唯一性(3.7+保序) | o(n) | 字典插入顺序保留特性 |
列表推导式+in判断 | 线性查找 | o(n²) | 列表原生索引机制 |
pandas.series.drop_duplicates() | 哈希表+向量化运算 | o(n) | pandas库(基于numpy) |
sorted(list(groupby(lst))) | 排序+分组 | o(n log n) | itertools模块 |
set去重快的本质:集合的底层是哈希表,每个元素的查找时间为o(1),去重过程相当于“遍历列表+哈希表去重”,全程线性时间。但哈希表的无序性导致原列表顺序被打乱,且仅支持可哈希元素(数字、字符串、元组)。dict.fromkeys()保序的秘密:python 3.7+重构了字典实现,保证键的插入顺序与存储顺序一致。dict.fromkeys(lst)利用“键不可重复”特性去重,同时保留原列表顺序,时间复杂度与set相当,但比set多了顺序维护的微小开销。drop_duplicates()底层基于numpy的向量化运算,避免python循环的解释器开销,且支持复杂条件过滤(如按字段去重、保留最后一次出现元素),但需额外依赖库。timeit执行10次取平均值,排除系统波动影响| 方法 | 1万条数据 | 10万条数据 | 100万条数据 | 保序性 | 支持复杂过滤 |
|---|---|---|---|---|---|
set(lst) | 0.0008 | 0.003 | 0.028 | ❌ | ❌ |
list(dict.fromkeys(lst)) | 0.0012 | 0.005 | 0.042 | ✅ | ❌ |
列表推导式[x for x in lst if x not in new_lst] | 0.12 | 11.8 | 1203.5 | ✅ | ✅ |
pd.series(lst).drop_duplicates().tolist() | 0.004 | 0.012 | 0.095 | ✅ | ✅ |
sorted(list(groupby(lst))) | 0.003 | 0.035 | 0.41 | ✅ | ❌ |
drop_duplicates()时间复杂度为o(n),与实测100万条数据0.095秒的线性表现吻合# 低效代码(12分钟耗时)
logs = [str(random.randint(1, 500000)) for _ in range(1000000)]
unique_logs = []
for log in logs:
if log not in unique_logs: # 每次判断都是o(n)查找
unique_logs.append(log)
cprofile分析发现,if log not in unique_logs占总耗时的99.7%dict.fromkeys()(保序+高效)# 优化后代码(0.3秒耗时) unique_logs = list(dict.fromkeys(logs)) # o(n)时间复杂度
import pandas as pd
# 读取数据(避免excel崩溃问题)
df = pd.read_csv("salary_data.csv", low_memory=false)
# 去重+条件过滤(1.2秒完成)
unique_salary = df.drop_duplicates(
subset=["employee_id", "salary_date"], # 按员工id+薪资日期去重
keep="last" # 保留最后一条记录
).query("salary > 10000") # 过滤高薪数据
list(set(lst))处理需保序的业务数据(如时序日志)dict.fromkeys(),低版本用collections.ordereddict# 保序去重最优解(3.7+) unique_lst = list(dict.fromkeys(lst)) # 兼容低版本(3.6-) from collections import ordereddict unique_lst = list(ordereddict.fromkeys(lst))
[{1:2}, {1:2}])typeerror: unhashable type: 'dict'def deduplicate_unhashable(lst, key_func=none):
"""处理不可哈希元素的去重"""
seen = set()
result = []
for item in lst:
# 用自定义key函数提取可哈希特征
key = key_func(item) if key_func else str(item)
if key not in seen:
seen.add(key)
result.append(item)
return result
# 示例:去重包含字典的列表
lst = [{"id":1}, {"id":2}, {"id":1}]
unique_lst = deduplicate_unhashable(lst, key_func=lambda x: x["id"])
import pandas as pd import numpy as np lst = [1, 2, np.nan, 2, np.nan] # 统一处理逻辑:将nan视为重复 unique_lst = pd.series(lst).drop_duplicates(keep="first").tolist()
[x for x in lst if x not in new_lst]timeit测试不同数据量下的耗时,观察增长趋势set或dict.fromkeys()dict.fromkeys(lst)ordereddict或升级python版本graph td
a[需求场景] --> b{是否保序}
b -->|否| c{数据量}
b -->|是| d{数据量}
c -->|≤1万| e[set(lst) 简洁优先]
c -->|>1万| f[set(lst) 效率优先]
d -->|≤10万| g[dict.fromkeys(lst) 原生无依赖]
d -->|>10万| h{是否需要复杂过滤}
h -->|是| i[pandas.drop_duplicates() 功能优先]
h -->|否| j[dict.fromkeys(lst) 效率优先]
list.dedup()原生方法,整合保序与高效特性dict.fromkeys(),无序用set(),代码简洁优先;dict.fromkeys(),需过滤选pandas,避免任何o(n²)方案;以上就是python对list列表去重的五种方案的详细内容,更多关于python list列表去重的资料请关注代码网其它相关文章!
您想发表意见!!点此发布评论
版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。
发表评论