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

时间:2010-11-12 21:36:40

标签: python mysql sqlobject

我有一个对象列表,我有一个充满记录的数据库表。我的对象列表有一个title属性,我想从列表中删除任何具有重复标题的对象(保留原始对象)。

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

我已经看到了从列表中删除重复项的解决方案:myList = list(set(myList)),但我不确定如何使用对象列表执行此操作?

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

7 个答案:

答案 0 :(得分:35)

set(list_of_objects)只会在知道重复内容时删除重复项,也就是说,您需要定义对象的唯一性。

为了做到这一点,你需要使对象可以清洗。您需要定义__hash____eq__方法,方法如下:

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

但是,您可能只需要定义__eq__方法。

编辑:如何实施__eq__方法:

正如我所提到的,你需要知道对象的唯一性定义。假设我们有一本带有属性author_name和title的书,他们的组合是独一无二的(因此,我们可以有许多书籍由Stephen King撰写,很多书名为The Shining,但只有一本书名为The Shining by Stephen King),然后执行如下:

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))

您可以检查如果您创建一个包含相同作者和标题的2本书的列表,则书籍对象将相同(使用is运算符)和相等(使用{{ 1}}运营商)。此外,使用==时,它会删除一本书。

编辑:这是我的一个旧版本,但我现在才注意到它的错误在最后一段中用删除线修正:具有相同set()的对象赢了与hash()相比,不会给True。但是,如果您打算将它们用作集合的元素或作为字典中的键,则使用对象的可用性。

答案 1 :(得分:9)

由于它们不可清洗,因此您无法直接使用它。标题应该是。

这是第一部分。

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等。

答案 2 :(得分:1)

这似乎很小:

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

答案 3 :(得分:0)

为此需要__hash____eq__

python's sets are implemented as hashtables开始,需要

__hash__将对象添加到集合中。默认情况下,不可变对象(例如数字,字符串和元组)是可哈希的。

但是,由于信鸽原理,哈希冲突(两个不同的对象哈希到相同的值)是不可避免的。因此,不能仅使用其哈希来区分两个对象,并且用户必须指定自己的__eq__函数。因此,用户提供的实际哈希函数并不是至关重要的,尽管最好是避免哈希冲突以提高性能(请参见What's a correct and good way to implement __hash__()?)。

答案 4 :(得分:0)

我最近最终使用了下面的代码。它与其他答案类似,因为它会遍历列表并记录所看到的内容,然后删除它已经看到的任何项目,但不会创建重复的列表,而是从原始列表中删除该项目。

seen = {}
for obj in objList:
    if obj["key-property"] in seen.keys():
        objList.remove(obj)
    else:
        seen[obj["key-property"]] = 1

答案 5 :(得分:-2)

如果您想保留原始订单,请使用它:

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

如果您不在乎订购,请使用它:

new_list = list(set(my_list))

答案 6 :(得分:-6)

很容易取消: -

  
    
      

a = [5,6,7,32,32,32,32,32,32,32,32]

             

a = list(set(a))

             

print(a)

    
  
[5,6,7,32]
那就是它! :)