2012-06-18 58 views
80

的名單比方說,我有一個字典列表:Python的 - 獨特的字典

[ 
    {'id': 1, 'name': 'john', 'age': 34}, 
    {'id': 1, 'name': 'john', 'age': 34}, 
    {'id': 2, 'name': 'hanna', 'age': 30}, 
] 

,我需要獲得獨特的詞典列表(刪除重複項):

[ 
    {'id': 1, 'name': 'john', 'age': 34}, 
    {'id': 2, 'name': 'hanna', 'age': 30}, 
] 

任何人都可以幫助我以最有效的方式在Python中實現這一目標?

+3

如何廣泛的是這些字典?你需要單獨的屬性檢查來確定重複項,還是檢查其中的單個值是否足夠? –

+0

這些字符有8個關鍵:值對,列表中有200個字符。他們實際上得到了一個ID,如果發現ID值是重複的,我可以從列表中刪除字典。 – Limaaf

+0

[How to make values in dictionary list is unique?](http://stackoverflow.com/questions/31792680/how-to-make-values-in-list-of-dictionary-unique) – Abhijeet

回答

123

因此,使用id作爲臨時字典。這會過濾出重複項。 的字典的values()將是列表

在Python2.7

>>> L=[ 
... {'id':1,'name':'john', 'age':34}, 
... {'id':1,'name':'john', 'age':34}, 
... {'id':2,'name':'hanna', 'age':30}, 
... ] 
>>> {v['id']:v for v in L}.values() 
[{'age': 34, 'id': 1, 'name': 'john'}, {'age': 30, 'id': 2, 'name': 'hanna'}] 

在Python3

>>> L=[ 
... {'id':1,'name':'john', 'age':34}, 
... {'id':1,'name':'john', 'age':34}, 
... {'id':2,'name':'hanna', 'age':30}, 
... ] 
>>> list({v['id']:v for v in L}.values()) 
[{'age': 34, 'id': 1, 'name': 'john'}, {'age': 30, 'id': 2, 'name': 'hanna'}] 

在的python2.5/2.6

>>> L=[ 
... {'id':1,'name':'john', 'age':34}, 
... {'id':1,'name':'john', 'age':34}, 
... {'id':2,'name':'hanna', 'age':30}, 
... ] 
>>> dict((v['id'],v) for v in L).values() 
[{'age': 34, 'id': 1, 'name': 'john'}, {'age': 30, 'id': 2, 'name': 'hanna'}] 
+0

這樣做的工作=)幾乎所有的答案是正確的,並幫助我。將其標記爲包含python版本diff代碼的正確答案。歡呼所有幫助我的人。 – Limaaf

+0

@John La Rooy - 如何使用同一個從基於多個屬性的列表中刪除字典,嘗試過但似乎不工作> {v ['flight'] ['lon'] ['lat']:v對於流中的v} .values() –

+0

@JorgeVidinha假設每個都可以轉換爲str(或unicode),試試這個:{str(v ['flight'])+':'+ str(v ['lon' ])+','+ str(v ['lat']):v for v in stream} .values()'這只是根據你的值創建一個唯一的鍵。像'MH370:-21.474370,86.325589'' – whunterknight

0

這是我找到的解決方案:

usedID = [] 

x = [ 
{'id':1,'name':'john', 'age':34}, 
{'id':1,'name':'john', 'age':34}, 
{'id':2,'name':'hanna', 'age':30}, 
] 

for each in x: 
    if each['id'] in usedID: 
     x.remove(each) 
    else: 
     usedID.append(each['id']) 

print x 

基本上你檢查ID出現在列表中,如果是,刪除字典,如果沒有,ID添加到列表中

+0

我想使用usedID而不是list。這是一個更快的查找,更可讀 – happydave

+0

是啊,我不知道關於集......但我正在學習......我只是看着@gnibbler答案...... – tabchas

+0

你需要測試一下更多。在迭代時修改列表可能並不總是如你所願 –

49

通常的方式找到只是一組共同要素是使用Python的set類。只需將所有元素添加到該集合中,然後將該集合轉換爲list,並且bam中的副本消失了。

問題當然是,set()只能包含可排序條目,並且dict不可排列。

如果我有這個問題,我的解決辦法是給每個dict轉換成表示dict一個字符串,那麼所有的字符串添加到set()然後讀出字符串值作爲list()和轉換回dict

以字符串形式表示dict是JSON格式。 Python有一個用於JSON的內置模塊(當然稱爲json)。

剩下的問題是dict中的元素沒有排序,當Python將dict轉換爲JSON字符串時,可能會得到兩個代表等效字典但不是相同字符串的JSON字符串。簡單的解決方法是在撥打json.dumps()時通過參數sort_keys=True

編輯:此解決方案假設給定dict可以有任何不同的部分。如果我們可以假設每個dict的值與"id"的值相同,則每隔一個dict的值與"id"的值相同,則這是過度殺傷; @ gnibbler的解決方案會更快更輕鬆。

編輯:現在有來自AndréLima明確表示如果ID是重複的評論,可以安全地假設整個dict是重複的。所以這個答案是矯枉過正的,我推薦@ gnibbler的回答。

+0

感謝steveha的幫助。你的答案實際上給了我一些我沒有的知識,因爲我剛剛開始使用Python =) – Limaaf

+1

雖然在這種特殊情況下ID已經過分誇大了,但這仍然是一個很好的答案! –

+4

這可以幫助我,因爲我的字典沒有密鑰,只能通過它的所有條目唯一標識。謝謝! – ericso

7

由於id已足夠用於檢測重複項,並且id是可排序的:通過以id爲關鍵字的字典運行'em'。每個鍵的值是原始字典。

deduped_dicts = dict((item["id"], item) for item in list_of_dicts).values() 

在Python 3中,values()不返回一個列表;你需要換整個表達式的右手側list(),你可以更經濟地寫出表達的肉作爲字典理解:

deduped_dicts = list({item["id"]: item for item in list_of_dicts}.values()) 

注意,結果可能會不順序與原文相同。如果這是要求,您可以使用Collections.OrderedDict而不是dict

順便說一句,它可能會使保持數據在一個字典中使用id作爲關鍵開始。

9

這裏有一個相當緊湊的解決方案,雖然我懷疑不是特別有效(說得客氣一點):

>>> ds = [{'id':1,'name':'john', 'age':34}, 
...  {'id':1,'name':'john', 'age':34}, 
...  {'id':2,'name':'hanna', 'age':30} 
...  ] 
>>> map(dict, set(tuple(sorted(d.items())) for d in ds)) 
[{'age': 30, 'id': 2, 'name': 'hanna'}, {'age': 34, 'id': 1, 'name': 'john'}] 
+1

在Python 3中用'list()'調用'map()'調用以獲取列表,否則它是一個'map'對象。 – dmn

0

非常簡單的選擇:

L = [ 
    {'id':1,'name':'john', 'age':34}, 
    {'id':1,'name':'john', 'age':34}, 
    {'id':2,'name':'hanna', 'age':30}, 
    ] 


D = dict() 
for l in L: D[l['id']] = l 
output = list(D.values()) 
print output 
0

繼承人與小內存開銷的實現成本不像其他的一樣緊湊。

values = [ {'id':2,'name':'hanna', 'age':30}, 
      {'id':1,'name':'john', 'age':34}, 
      {'id':1,'name':'john', 'age':34}, 
      {'id':2,'name':'hanna', 'age':30}, 
      {'id':1,'name':'john', 'age':34},] 
count = {} 
index = 0 
while index < len(values): 
    if values[index]['id'] in count: 
     del values[index] 
    else: 
     count[values[index]['id']] = 1 
     index += 1 

輸出:

[{'age': 30, 'id': 2, 'name': 'hanna'}, {'age': 34, 'id': 1, 'name': 'john'}] 
+1

您需要再測試一下。在迭代時修改列表可能並不總是如你期望的那樣工作 –

+0

@gnibbler非常好!我會刪除答案並更徹底地進行測試。 –

+0

@gnibbler更好嗎? –

6
a = [ 
{'id':1,'name':'john', 'age':34}, 
{'id':1,'name':'john', 'age':34}, 
{'id':2,'name':'hanna', 'age':30}, 
] 

b = {x['id']:x for x in a}.values() 

print(b) 

輸出:

[{'age': 34, 'id': 1, 'name': 'john'}, {'age': 30, 'id': 2, 'name': 'hanna'}]

+0

在同一個例子中。我怎樣才能得到只包含類似ID的字典? – user8162

+0

@ user8162,你想要輸出看起來像什麼? –

+0

有時,我會有相同的ID,但不同的年齡。所以輸出爲[{'age':[34,40],'id':1,'name':['john',Peter]}]。簡而言之,如果ID相同,則將其他人的內容組合到列表中,如我在此提到的。提前致謝。 – user8162

16

您可以使用numpy的庫(僅適用於Python2.x):

import numpy as np 

    list_of_unique_dicts=list(np.unique(np.array(list_of_dicts))) 
+6

在Python 3.5中執行此操作時,發生錯誤「TypeError:unorderable types:dict()> dict()」。 – Guillochon

7

如果字典僅由所有項目唯一標識(ID不可用),則可以使用JSON使用答案。以下是不使用JSON,並且將只通過生成一個新的列表,只要所有的字典中的值是不可變的

[dict(s) for s in set(frozenset(d.items()) for d in L)] 
0

快速和骯髒的解決方案是工作的一種替代。

sortedlist = [] 

for item in listwhichneedssorting: 
    if item not in sortedlist: 
     sortedlist.append(item) 
1

擴展在約翰·拉ROOY(Python - List of unique dictionaries)的答案,使其多一點靈活:

def dedup_dict_list(list_of_dicts: list, columns: list) -> list: 
    return list({''.join(row[column] for column in columns): row 
       for row in list_of_dicts}.values()) 

調用功能:

sorted_list_of_dicts = dedup_dict_list(
    unsorted_list_of_dicts, ['id', 'name'])