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

Python中如何从列表中移除可变对象的重复项?

去除列表中可变对象的重复项

不可变对象的常规去重

当列表由不可变对象(比如整数、字符串)组成时,去除重复项直接用set(lst)即可:

lst = [0,4,2,6,3,6,4,9,2,2] # Python中整数是不可变类型
print(set(lst)) # {0,2,3,4,6,9}

可变对象去重的痛点

如果列表包含可变对象(比如dict、list),set(lst)会直接报错——因为可变对象不可哈希,会触发TypeError: unhashable type: '<type>'。

举个例子,下面的列表里有多个重复引用的dict:

d0 = {0:'a', 1:'b', 9:'j'}
d1 = {'jan':1, 'jul':7, 'dec':12}
d2 = {'hello':'hola', 'goodbye':'adios', 'happy':'feliz', 'sad':'triste'}
lst = [d0, d1, d1, d0, d2, d1, d0]

我们希望遍历列表时每个dict只处理一次,但用set(lst)会抛出TypeError: unhashable type: 'dict'。

基础实现:利用对象ID去重

可以通过对象的id()来判断是否为同一对象(同一对象的ID唯一),实现一个生成器函数:

def dedup(lst):
  seen_ids = set()
  for elem in lst:
    id_ = id(elem)
    if id_ not in seen_ids:
      seen_ids.add(id_)
      yield elem

更优的实现方案

1. 用itertools简化逻辑

借助itertools.filterfalse封装判断逻辑,代码更简洁模块化:

from itertools import filterfalse

def dedup(lst):
    seen_ids = set()
    def is_duplicate(elem):
        elem_id = id(elem)
        if elem_id in seen_ids:
            return True
        seen_ids.add(elem_id)
        return False
    return filterfalse(is_duplicate, lst)

功能和基础实现完全一致,但结构更清晰。

2. 按对象内容去重(而非引用)

如果你的需求是内容相同的可变对象也视为重复(比如两个不同但键值对完全一样的dict),上面的方法就不适用了。这时可以把可变对象转换成可哈希的类型,比如将dict转成排序后的元组:

def dedup_by_value(lst):
    seen = set()
    for elem in lst:
        # 对dict的items排序后转元组,确保内容相同的dict生成相同的键
        key = tuple(sorted(elem.items()))
        if key not in seen:
            seen.add(key)
            yield elem

比如对于d0 = {0:'a',1:'b'}和d3 = {1:'b',0:'a'},这个方法会将它们视为重复项,只保留第一个出现的对象。

3. 直接返回列表(非生成器)

如果不需要生成器,而是要直接得到去重后的列表,可以用常规的循环+列表的写法:

def dedup_list(lst):
    seen_ids = set()
    result = []
    for elem in lst:
        elem_id = id(elem)
        if elem_id not in seen_ids:
            seen_ids.add(elem_id)
            result.append(elem)
    return result

这个写法更直观,适合不需要惰性求值的场景。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 15:51:41