本文目录导读:
- 使用 set (最简单,不保留顺序)
- 使用 dict.fromkeys() (Python 3.7+ 保留插入顺序)
- 使用列表推导式 + 集合辅助(经典保留顺序法)
- 使用 itertools.groupby (适用于已排序的列表)
- 使用 pandas (数据科学场景)
- 处理不可哈希元素(列表嵌套列表等)
- 保持顺序且元素不可哈希(使用
dict+repr作为键) - 使用
ordered-set第三方库 - 总结对比
列表去重(即移除列表中重复的元素)是数据处理中的常见需求,根据不同的应用场景(是否需要保持顺序、是否需要考虑嵌套元素或哈希性等),Python中主要有以下几种实现方法:
使用 set (最简单,不保留顺序)
set 是无序的、元素唯一的集合,直接转换会丢失原始顺序。
my_list = [1, 2, 2, 3, 1, 4] dedup_list = list(set(my_list)) print(dedup_list) # 输出可能是 [1, 2, 3, 4] 或 [2, 1, 3, 4],顺序不可控
注意:set 中的元素必须是可哈希的(如数字、字符串、元组),如果列表包含列表、字典等不可哈希类型会报错。
使用 dict.fromkeys() (Python 3.7+ 保留插入顺序)
利用字典的键唯一且有序(Python 3.7及以上版本)的特性。
my_list = [1, 2, 2, 3, 1, 4] dedup_list = list(dict.fromkeys(my_list)) print(dedup_list) # [1, 2, 3, 4] (顺序保留)
优点:写法简洁,且能保留顺序,适用于可哈希元素。
使用列表推导式 + 集合辅助(经典保留顺序法)
手动维护一个已经出现过的元素的集合,只添加未出现过的元素。
my_list = [1, 2, 2, 3, 1, 4]
seen = set()
dedup_list = []
for item in my_list:
if item not in seen:
seen.add(item)
dedup_list.append(item)
print(dedup_list) # [1, 2, 3, 4]
优点:清晰易懂,保留顺序,且时间复杂度为 O(n),适用于可哈希元素。
使用 itertools.groupby (适用于已排序的列表)
如果列表已经排序,可以利用 groupby 去重,但不排序的话需要先排序,会改变顺序。
from itertools import groupby my_list = [1, 1, 2, 2, 3, 4] # 假设已排序 dedup_list = [key for key, _ in groupby(my_list)] print(dedup_list) # [1, 2, 3, 4]
适用场景:数据已按某种规则排好序,或你不在乎排序。
使用 pandas (数据科学场景)
如果是处理数据框或大型数据,pandas 提供高效的 duplicated() 方法。
import pandas as pd my_list = [1, 2, 2, 3, 1, 4] series = pd.Series(my_list) dedup_list = series.drop_duplicates().tolist() print(dedup_list) # [1, 2, 3, 4] (默认保留第一次出现的值)
处理不可哈希元素(列表嵌套列表等)
对于嵌套列表、字典等内容,set 和直接 in 检查会失效,此时需要遍历并比较元素值。
方法: 将每个子元素转换为可哈希的表示(如转成元组或字符串)。
# 针对列表包含列表的情况
my_list = [[1, 2], [1, 2], [3, 4], [3, 4]]
# 方法1:转成元组后用set
dedup_list = list(set(tuple(sublist) for sublist in my_list))
dedup_list = [list(item) for item in dedup_list] # 转回列表
# 方法2:遍历并比较值(更通用,但不保证顺序)
seen = []
for inner in my_list:
if inner not in seen:
seen.append(inner)
print(seen) # [[1, 2], [3, 4]]
注意:inner not in seen 对于嵌套列表会逐个比较元素,性能较差(O(n²)),但对不可哈希数据是有效方案。
保持顺序且元素不可哈希(使用 dict + repr 作为键)
将不可哈希元素转化为可哈希的 repr 字符串作为字典键,利用 dict.fromkeys 保留顺序。
my_list = [[1, 2], [1, 2], [3, 4], [3, 4]]
dedup_list = list(dict.fromkeys(repr(item) for item in my_list))
# 但这里得到的是字符串表示,可以配合 eval 恢复(小心安全问题)
dedup_list = [eval(item) for item in dedup_list]
# 更安全:使用 json.dumps 作为键
import json
seen = {}
for item in my_list:
key = json.dumps(item, sort_keys=True) # 标准化
if key not in seen:
seen[key] = item
dedup_list = list(seen.values())
使用 ordered-set 第三方库
如果需要频繁保留顺序的去重,可以安装 ordered-set:
pip install ordered-set
from ordered_set import OrderedSet my_list = [1, 2, 2, 3, 1, 4] dedup_list = list(OrderedSet(my_list)) # [1, 2, 3, 4]
总结对比
| 方法 | 保留顺序 | 元素要求 | 适用场景 |
|---|---|---|---|
set() |
可哈希 | 不需要顺序,简单快速 | |
dict.fromkeys() |
可哈希 | 需要保留顺序,可哈希元素 | |
列表推导式 + seen 集合 |
可哈希 | 通用保留顺序,清晰 | |
itertools.groupby |
需排序 | 可哈希/可比较 | 已排序或不在乎顺序 |
pandas.drop_duplicates |
默认保留第一个 | 几乎任意 | 数据分析、大型数据 |
| 嵌套列表手动比较 | 可保留 | 任意(包括不可哈希) | 列表包含列表/字典等复杂类型 |
选择建议:
- 简单场景(元素可哈希):用
dict.fromkeys()或列表推导式 +set。 - 元素不可哈希:用遍历
in比较或转成字符串/元组作为键。 - 大型数据或机器学习:用 pandas 更高效。
标签: 列表去重