Python中如何对对象列表去重?要求仅i==j时对象引用相等
在Python中基于对象身份(
is)对可变对象列表去重 我太懂这个痛点了——当你要对可变/不可哈希对象列表按对象身份(也就是is判断相等)去重时,常规的set()方法直接歇菜,毕竟像set这种可变类型没法哈希。而且你要的不是值相等,是完全同一个对象实例:只有当list_of_objects[i] is list_of_objects[j]时才认为是重复项,对吧?
核心思路:用id()获取对象的唯一标识
Python里每个对象实例在其生命周期内都有一个唯一的id,这相当于我们能拿到一个“隐形指针”,不管对象是不是可哈希,都能用它来判断是不是同一个实例。基于这个思路,我们可以直接实现去重。
方法1:自定义函数(清晰易懂,兼容所有Python版本)
这个方法遍历列表,记录已经见过的对象id,只保留首次出现的实例:
def deduplicate_by_identity(obj_list): seen_ids = set() unique_objects = [] for obj in obj_list: obj_id = id(obj) if obj_id not in seen_ids: seen_ids.add(obj_id) unique_objects.append(obj) return unique_objects
测试示例1:
a = {1,2,3} b = {4,5,6} cur_dict = {1:a, 2:a, 3:a, 4:b, 5:b, 6:b} duplicated_clusters = list(cur_dict.values()) print(deduplicate_by_identity(duplicated_clusters)) # 输出 [{1, 2, 3}, {4, 5, 6}]
测试示例2:
a = {1,2,3} b = {4,5,6} c = {1,2,3} duplicated_clusters = [a,a,b,b,c,c] print(deduplicate_by_identity(duplicated_clusters)) # 输出 [{1,2,3}, {4,5,6}, {1,2,3}],等价于[a,b,c]
方法2:一行代码实现(Python 3.7+,利用字典插入顺序)
从Python 3.7开始,字典会保留键的插入顺序,我们可以用字典推导式快速去重:
deduplicated_clusters = list({id(obj): obj for obj in duplicated_clusters}.values())
原理和上面的函数完全一致:用对象的id作为字典的键(自动去重),最后取字典的值就是唯一的对象实例列表。
对比你的临时方案
这个方法比你之前维护名字映射字典的方案更直接,不需要额外的中间字典,直接操作对象本身,减少了代码的复杂度和出错概率。
注意事项
id()的唯一性只在对象的生命周期内有效:如果某个对象被垃圾回收了,它的id可能会被复用,但在处理列表的过程中,只要列表里的对象都还存活,id就是完全可靠的。
内容的提问来源于stack exchange,提问作者Dau Zi
相关产品推荐
相关产品推荐

