2010-11-12 188 views
12

我有一个对象列表,并且我有一个充满记录的db表。我的对象列表具有标题属性,我想从列表中删除具有重复标题的任何对象(保留原始对象)。用Python删除对象列表中的重复项

然后我想检查我的对象列表是否有数据库中任何记录的任何重复项,如果是,请在将它们添加到数据库之前从列表中删除这些项。

我已经看到了从这样的列表中删除重复项的解决方案:myList = list(set(myList)),但我不知道如何使用对象列表来做到这一点?

我也需要维护对象列表的顺序。我也在想,也许我可以用difflib来检查标题中的差异。

+4

步骤1.搜索。在Python编程类中每学期都会使用这种确切的措词。请搜索。 – 2010-11-12 21:38:45

+0

__leaving original__,这是什么意思?因为如果像你说过的那样,你希望__维护列表中的order__,那么列表中第一次出现重复对象将是原始权利? – mouad 2010-11-12 21:56:24

+0

是的,我的意思是我想删除除原来的所有副本。 @ S.Lott,我搜索了很多东西,但没有找到任何东西,这就是我来到这里的原因。你能举出一个解决这个确切问题的例子吗?我很乐意看到它。 – imns 2010-11-12 22:25:22

回答

28

set(list_of_objects)如果你知道一个重复的是什么,只会删除重复的,也就是说,你需要定义一个对象的唯一性。

为了做到这一点,您需要使对象可哈希。您需要定义两个__hash____eq__方法,这里是如何:

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

虽然,你可能只需要定义__eq__方法。

编辑:如何实现__eq__方法:

你需要知道,正如我所说,你的对象的唯一性定义。假设我们有一本带有属性author_name和title的书,它们的组合是独一无二的(所以我们可以有很多Stephen King编写的书,还有很多书叫做The Shining,但只有一本书叫Stephen King的Shining),那么实现如下:

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()时,它将删除一本书。

编辑:这是我的一个老anwser,但我现在才发现,它具有与删除线最后一段更正错误:与同hash()对象时is相比不会给True 。但是,如果您打算将它们用作集合的元素,或者将其用作字典中的键,则可以使用对象的可哈希性。

+0

不错,我不知道'__hash__'和'__eq__'。任何关于如何实现'__eq__'的例子? – imns 2010-11-14 17:02:19

+0

请参阅上面的编辑 – vonPetrushev 2010-11-15 13:09:49

6

由于它们不可散列,因此不能直接使用集合。标题应该是。

这是第一部分。

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等你用于第二部分虽然。

+0

我在sqlobject中使用mysql。 – imns 2010-11-12 22:07:50

+0

@bababa请更新问题,以便其他人也能看到它。 – aaronasterling 2010-11-12 22:14:52

+0

@bababa,我没有看到使用sqlobject做这件事的好方法(也就是说,在一个查询中没有从数据库中拉出每个对象,或者每个对象都有一个查询),所以我会等一会儿,然后发布,如果有人不知道比我更好的sqlobject不来。 – aaronasterling 2010-11-12 23:49:30

1

这似乎相当小:

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

其相当容易freinds: -

一个= [5,6,7,32,32,32,32,32,32,32,32]

一个=列表(集的(a))

打印的(a)

[5,6,7,32] 

多数民众赞成它! :)

+5

无法在包含对象的列表上执行此操作。 – 2014-09-21 00:00:45

0

如果你想保留原来的顺序使用:

seen = {} 
new_list = [seen.setdefault(x, x) for x in my_list if x not in seen] 

如果你不在乎订购然后用它的:

new_list = list(set(my_list))