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

为何Python用set()去重字典时报TypeError?如何高效保序去重?

为什么Python字典不可哈希?如何高效去除列表中重复字典并保留顺序?

一、字典不可哈希的原因

Python中,一个对象能被哈希(即可以作为set的元素或dict的键)必须满足两个核心条件:

  • 不可变性:对象的内容不能被修改;
  • 哈希值稳定:对象的__hash__()方法必须返回固定不变的值,无论何时调用。

而字典是可变容器——你可以随时添加、删除或修改它的键值对。如果允许字典被哈希,当你修改字典内容后,它的哈希值会随之改变,这会导致依赖哈希的数据结构(比如set)出现逻辑混乱:比如你把字典加入set后修改它,set将无法再定位到这个元素,破坏了集合的唯一性约束。因此Python直接将字典标记为不可哈希类型,禁止它作为set元素或dict键。

二、去除重复字典并保留顺序的高效方法

Python 3.7+的内置dict会保留插入顺序,利用这个特性可以实现O(n)时间复杂度的高效去重,以下是几种常用方案:

1. 利用唯一标识键(最快,适用于有唯一键的场景)

如果你的字典有天然的唯一标识(比如示例中的id字段),直接用这个键作为字典的键来去重:

items = [
    {'id': 1, 'name': 'Alice'},
    {'id': 2, 'name': 'Bob'},
    {'id': 1, 'name': 'Alice'}
]

unique_dict = {d['id']: d for d in items}
result = list(unique_dict.values())
print(result)

输出:

[{'id': 1, 'name': 'Alice'}, {'id': 2, 'name': 'Bob'}]

2. 无唯一键时,转成可哈希的元组(通用方案)

如果字典没有唯一键,将字典的键值对转成排序后的元组(确保相同内容的字典生成相同的元组),再用字典推导式去重:

items = [
    {'id': 1, 'name': 'Alice'},
    {'id': 2, 'name': 'Bob'},
    {'id': 1, 'name': 'Alice'}
]

# 排序键值对是为了避免因键的顺序不同导致元组不同
unique_dict = {tuple(sorted(d.items())): d for d in items}
result = list(unique_dict.values())
print(result)

如果你的字典键的顺序固定(比如所有相同内容的字典键顺序一致),可以省略sorted(),直接用tuple(d.items()),效率会更高。

3. 手动维护已见集合(可读性强)

遍历列表时维护一个存储已见哈希键的集合,只添加未出现过的字典:

items = [
    {'id': 1, 'name': 'Alice'},
    {'id': 2, 'name': 'Bob'},
    {'id': 1, 'name': 'Alice'}
]

seen = set()
result = []
for d in items:
    key = tuple(sorted(d.items()))
    if key not in seen:
        seen.add(key)
        result.append(d)
print(result)

这个方法和字典推导式效率相当,适合需要更细粒度控制的场景。


内容的提问来源于stack exchange,提问作者user32747404

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.02 07:22:30