列表去重的方法有哪些?

访客 python案例 5

本文目录导读:

  1. 使用 set (最简单,不保留顺序
  2. 使用 dict.fromkeys() (Python 3.7+ 保留插入顺序)
  3. 使用列表推导式 + 集合辅助(经典保留顺序法)
  4. 使用 itertools.groupby (适用于已排序的列表)
  5. 使用 pandas (数据科学场景)
  6. 处理不可哈希元素(列表嵌套列表等)
  7. 保持顺序且元素不可哈希(使用 dict + repr 作为键)
  8. 使用 ordered-set 第三方库
  9. 总结对比

列表去重(即移除列表中重复的元素)是数据处理中的常见需求,根据不同的应用场景(是否需要保持顺序、是否需要考虑嵌套元素或哈希性等),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 更高效。

标签: 列表去重

抱歉,评论功能暂时关闭!