用Python去除对象列表中的重复项
我有一个对象列表,还有一个数据库表里面满是记录。我的对象列表里每个对象都有一个标题属性,我想把那些标题重复的对象去掉,只保留一个原始的。
接下来,我想检查我的对象列表里是否有和数据库中记录重复的标题,如果有的话,就把这些重复的对象从列表中删掉,然后再把剩下的对象添加到数据库里。
我见过一些方法可以去掉列表中的重复项,比如用 myList = list(set(myList))
,但我不太确定怎么用在对象列表上。
我还需要保持我的对象列表的顺序。我也在想,或许可以用 difflib
来检查标题之间的差异。
8 个回答
这看起来非常简单:
new_dict = dict()
for obj in myList:
if obj.title not in new_dict:
new_dict[obj.title] = obj
因为它们不能被哈希,所以你不能直接使用集合。不过,标题是可以的。
这是第一部分。
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等。
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
。不过,如果你打算将它们用作集合的元素或字典的键,哈希性是很重要的。