2017-05-25 201 views
1

我有一個函數,我希望一次一個地瀏覽一個自定義對象(給定中點)列表,並將對象與獨特的中點對齊並放入一個新的列表。下面的代碼給了我一個錯誤,即列表沒有名爲'midPoint'的屬性,但是我不確定如何讓代碼在列表中搜索匹配中點的對象。有沒有人有建議?在python中通過屬性刪除對象列表中的重複項

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 
+0

https://stackoverflow.com/questions/4169252/remove-duplicates-in-list-of-object-with-python –

+0

的可能的複製'list_no_duplicates'是一個列表,並沒有一個' midPoint'屬性。如果你想看看這個屬性,你需要手頭有一個Object對象。另外,'list_no_duplicates.append(x)'行中的'x'是什麼? –

+0

是否要維護新列表中對象的順序? –

回答

1

您可以使用與sorted函數一起itertools.groupby從列表中刪除重複的條目。例如:

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

在這裏,我已經加入了__repr__()功能,以您的Obj類顯示的midPoint與你的類值對象:

def __repr__(self): 
    return 'Obj: midPoint {}'.format(str(self.midPoint)) 

注:該解決方案不會維護原始列表中元素的順序。新列表將根據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]] 
0

使用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'))] 

<script src="//repl.it/embed/ISOl/1.js"></script>

0

我們可以使用一個帶有setdefault的字典,將該鍵用作midPoint的元組,並將該值作爲列表添加到列表中,然後添加到該列表中。

那麼我們有與中點的每個值列表的字典,我們可以迭代出[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] 
0

如果你不關心在新的列表中的對象的順序,你可以使用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]] 

使用鍵作爲midPoint值的元組創建一個字典,並將值作爲Obj類的對象。然後調用dict.values()方法獲取值列表,即您的案例中的Obj對象列表。

但是,在Python 3.x中dict.values()返回一個dict_values類型的對象。爲了將其轉換爲列表,明確其類型強制轉換爲list爲:

new_list = list(new_list) 
0

如果我理解正確的話,這可能會按照您要求。

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 
相關問題