在python中按属性删除对象列表中的重复项

在python中按属性删除对象列表中的重复项,python,list,object,attributes,Python,List,Object,Attributes,我有一个函数,我想一次浏览一个自定义对象列表(具有给定的中点),并获取具有唯一中点的对象,然后将它们放入新列表中。下面的代码给了我一个错误,列表没有名为“中点”的属性,但我不确定如何获取代码来搜索列表中具有匹配中点的对象。有人有建议吗 class Obj(): def __init__(self, midPoint=[0,0]): self.midPoint = midPoint obj1 = Obj(midPoint = [1,1]) obj2 = Obj(midPo

我有一个函数,我想一次浏览一个自定义对象列表(具有给定的中点),并获取具有唯一中点的对象,然后将它们放入新列表中。下面的代码给了我一个错误,列表没有名为“中点”的属性,但我不确定如何获取代码来搜索列表中具有匹配中点的对象。有人有建议吗

class Obj():
    def __init__(self, midPoint=[0,0]):
        self.midPoint = midPoint

obj1 = Obj(midPoint = [1,1])
obj2 = Obj(midPoint = [2,2])
obj3 = Obj(midPoint = [3,3])
obj4 = Obj(midPoint = [1,1])
obj5 = Obj(midPoint = [2,2])

l = [obj1, obj2, obj3, obj4, obj5]

list_no_duplicates = []

def Delete_duplicates(list1):        
    for i in list1:
        if i.midPoint not in list_no_duplicates.midPoint:
        list_no_duplicates.append(x)

Delete_duplicates(l)
print list_no_duplicates
您可以使用with函数从列表中删除重复条目。例如:

>>> from itertools import groupby

>>> [next(obj) for i, obj in groupby(sorted(l, key=lambda x: x.midPoint), lambda x: x.midPoint)]
[Obj: midPoint [1, 1], Obj: midPoint [2, 2], Obj: midPoint [3, 3]]
在这里,我将函数添加到您的
Obj
类中,以显示带有类对象的
中点的值:

def __repr__(self):
    return 'Obj: midPoint {}'.format(str(self.midPoint))
注意:此解决方案不会保持原始列表中元素的顺序。新列表将根据
中点的值进行排序


以下是完整的代码供您参考:

from itertools import groupby

class Obj():
    def __init__(self, midPoint=[0,0]):
        self.midPoint = midPoint
    def __repr__(self):
        return 'Obj: midPoint {}'.format(str(self.midPoint))

obj1 = Obj(midPoint = [1,1])
obj2 = Obj(midPoint = [2,2])
obj3 = Obj(midPoint = [3,3])
obj4 = Obj(midPoint = [1,1])
obj5 = Obj(midPoint = [2,2])

l = [obj1, obj2, obj3, obj4, obj5]
# `print(l)` will display:
# [Obj: midPoint [1, 1], Obj: midPoint [2, 2], Obj: midPoint [3, 3], Obj: midPoint [1, 1], Obj: midPoint [2, 2]]

# New list with unique `midPoint`s
new_list = [next(obj) for i, obj in groupby(sorted(l, key=lambda x: x.midPoint), lambda x: x.midPoint)]
# `print(new_list)` will display:
# [Obj: midPoint [1, 1], Obj: midPoint [2, 2], Obj: midPoint [3, 3]]

使用
itertools.groupby

from itertools import groupby
from operator import attrgetter as ga
...
l2 = [next(g) for k, g in groupby(sorted(l, key=ga('midPoint')), key=ga('midPoint'))]

我们可以使用带有setdefault的dict,使用键作为中点的元组,使用值作为列表,然后将其附加到

然后我们有一个dict,其中每个中点的值都有一个列表,我们可以迭代第[0]个元素:

def Delete_duplicates(list1):
    deduped = {}
    for i in list1:
        deduped.setdefault(tuple(i.midPoint),[]).append(i)
    return [j[0] for i,j in deduped.items()]
如果您希望删除所有重复的列表,我们也可以这样做,但仅当列表长度为1时返回:

def Delete_duplicates(list1):
    deduped = {}
    for i in list1:
        deduped.setdefault(tuple(i.midPoint),[]).append(1)
    return [i for i in list1 if len(deduped[tuple(i.midPoint)]) == 1]

如果您不关心新列表中对象的顺序,可以使用
dict
来实现这一点:

new_list = {tuple(obj.midPoint): obj  for obj in l}.values()

# content of `new_list` will be:
# [Obj: midPoint [3, 3], Obj: midPoint [1, 1], Obj: midPoint [2, 2]]
创建一个字典,其中key作为
中点
值的元组,value作为
Obj
类的对象。然后调用
dict.values()
方法获取值列表,即案例中的
Obj
对象列表

但是,在Python3.x中,dict.values()返回一个dict.values类型的对象。要将其转换为列表,请显式键入cast to
list
,如下所示:

new_list = list(new_list)

如果我理解正确,这可能会按照你的要求工作

class Obj(): 
    def __init__(self, midPoint=[0,0]): 
        self.midPoint = midPoint

obj1 = Obj(midPoint = [1,1])
obj2 = Obj(midPoint = [2,2])
obj3 = Obj(midPoint = [3,3])
obj4 = Obj(midPoint = [1,1])
obj5 = Obj(midPoint = [2,2]) 

l = [obj1, obj2, obj3, obj4, obj5]
list_no_duplicates = [] 

# determines if midpoint already exists in any object inside list_no_duplicates
def midpoint_exists(midpoint):
    for obj in list_no_duplicates:
        if obj.midPoint == midpoint:
            return True
    return False

def Delete_duplicates(list1): 
    for obj in list1:
        # if there are no object with this midPoint, appends
        if not midpoint_exists(obj.midPoint):
            list_no_duplicates.append(obj)

Delete_duplicates(l)
print list_no_duplicates

列表的可能重复项\u无重复项
是一个列表,没有
中点
属性。如果希望查看此属性,则需要手头有一个
对象
对象。另外,在
列表无重复项。追加(x)
行中,什么是
x
?是否要在新列表中保持对象的顺序?是否要删除>=2个条目的对象,还是只保留其中一个?抱歉,我的意思是在“列表无重复项。追加(x)”中我不是x。订单不需要维护,我只想保留1份副本。谢谢