用Python去除对象列表中的重复项

51 投票
8 回答
64311 浏览
提问于 2025-04-16 07:00

我有一个对象列表,还有一个数据库表里面满是记录。我的对象列表里每个对象都有一个标题属性,我想把那些标题重复的对象去掉,只保留一个原始的。

接下来,我想检查我的对象列表里是否有和数据库中记录重复的标题,如果有的话,就把这些重复的对象从列表中删掉,然后再把剩下的对象添加到数据库里。

我见过一些方法可以去掉列表中的重复项,比如用 myList = list(set(myList)),但我不太确定怎么用在对象列表上。

我还需要保持我的对象列表的顺序。我也在想,或许可以用 difflib 来检查标题之间的差异。

8 个回答

6

这看起来非常简单:

new_dict = dict()
for obj in myList:
    if obj.title not in new_dict:
        new_dict[obj.title] = obj
28

因为它们不能被哈希,所以你不能直接使用集合。不过,标题是可以的。

这是第一部分。

seen_titles = set()
new_list = []
for obj in myList:
    if obj.title not in seen_titles:
        new_list.append(obj)
        seen_titles.add(obj.title)

不过,你需要说明一下你在第二部分使用的是哪种数据库或ORM等。

72

set(list_of_objects) 这个函数只有在你知道什么是重复的情况下,才能去掉重复的东西。也就是说,你需要定义一个对象的独特性。

为了做到这一点,你需要让这个对象可以被“哈希”。你需要定义两个方法:__hash____eq__,下面是怎么做的:

http://docs.python.org/glossary.html#term-hashable

不过,你可能只需要定义 __eq__ 这个方法。

编辑:如何实现 __eq__ 方法:

你需要知道,正如我提到的,你的对象的独特性定义是什么。假设我们有一本书,它的属性是作者名字和书名,它们的组合是独特的(也就是说,我们可以有很多斯蒂芬·金写的书,也可以有很多叫《闪灵》的书,但只有一本是斯蒂芬·金写的《闪灵》),那么实现方法如下:

def __eq__(self, other):
    return self.author_name==other.author_name\
           and self.title==other.title

类似地,这就是我有时实现 __hash__ 方法的方式:

def __hash__(self):
    return hash(('title', self.title,
                 'author_name', self.author_name))

你可以检查一下,如果你创建一个包含两本书的列表,它们的作者和书名都相同,那么这两个书对象会 是同一个(用 is 操作符)并且 相等(用 == 操作符)。另外,当使用 set() 时,它会去掉一本书。

编辑:这是我以前的一个旧回答,但我现在才注意到最后一段中有个错误,已经用删除线标出:具有相同 hash() 的对象在用 is 比较时不会返回 True。不过,如果你打算将它们用作集合的元素或字典的键,哈希性是很重要的。

撰写回答