[英]Find duplicates in python list of dictionaries
我有下面的字典:
a = [{'un': 'a', 'id': "cd"}, {'un': 'b', 'id': "cd"},{'un': 'b', 'id': "cd"}, {'un': 'c', 'id': "vd"},
{'un': 'c', 'id': "a"}, {'un': 'c', 'id': "vd"}, {'un': 'a', 'id': "cm"}]
我需要通過 'un' 鍵找到字典的副本,例如這個 {'un': 'a', 'id': "cd"} 和這個 {'un': 'a', 'id': " cm"} dicts 是由鍵 'un' 的值重復的,當找到重復項時,我需要決定保留什么 dict 關於它的鍵 'id' 的第二個值,例如我們將 dict 保留為模式值“cm” .
我已經完成了第一步,請參閱下面的代碼:
from collections import defaultdict
temp_ids = []
dup_dict = defaultdict(list)
for number, row in enumerate(a):
id = row['un']
if id not in temp_ids:
temp_ids.append(id)
else:
tally[id].append(number)
使用此代碼我或多或少能夠找到重復列表的索引,也許還有其他方法可以做到。 而且我還需要下一步代碼來決定保留什么和省略什么。 將非常感謝幫助。
一般情況下,如果要在字典列表中查找重復項,則應按照重復字典保留在同一組中的方式對字典進行分類。 為此,您需要根據dict
項目進行分類。 現在,因為對於字典,Order不是一個重要因素,您需要使用既可以清洗又不保持容器順序的容器。 frozenset()
是此任務的最佳選擇。
例:
In [87]: lst = [{2: 4, 6: 0},{20: 41, 60: 88},{5: 10, 2: 4, 6: 0},{20: 41, 60: 88},{2: 4, 6: 0}]
In [88]: result = defaultdict(list)
In [89]: for i, d in enumerate(lst):
...: result[frozenset(d.items())].append(i)
...:
In [91]: result
Out[91]:
defaultdict(list,
{frozenset({(2, 4), (6, 0)}): [0, 4],
frozenset({(20, 41), (60, 88)}): [1, 3],
frozenset({(2, 4), (5, 10), (6, 0)}): [2]})
在這種情況下,您可以根據'un'
鍵對詞典進行分類,然后根據id
選擇預期的項目:
>>> from collections import defaultdict
>>>
>>> d = defaultdict(list)
>>>
>>> for i in a:
... d[i['un']].append(i)
...
>>> d
defaultdict(<type 'list'>, {'a': [{'un': 'a', 'id': 'cd'}, {'un': 'a', 'id': 'cm'}], 'c': [{'un': 'c', 'id': 'vd'}, {'un': 'c', 'id': 'a'}, {'un': 'c', 'id': 'vd'}], 'b': [{'un': 'b', 'id': 'cd'}, {'un': 'b', 'id': 'cd'}]})
>>>
>>> keeps = {'a': 'cm', 'b':'cd', 'c':'vd'} # the key is 'un' and the value is 'id' should be keep for that 'un'
>>>
>>> [i for key, val in d.items() for i in val if i['id']==keeps[key]]
[{'un': 'a', 'id': 'cm'}, {'un': 'c', 'id': 'vd'}, {'un': 'c', 'id': 'vd'}, {'un': 'b', 'id': 'cd'}, {'un': 'b', 'id': 'cd'}]
>>>
在最后一行(嵌套列表理解)中,我們遍歷聚合的dict的項目然后在值上,並將這些項目保持在后面的值或條件中, i['id']==keeps[key]
,這意味着我們將保留具有指定值的id
的項目keeps
字典。
你可以將列表理解變成這樣的東西:
final_list = []
for key, val in d.items():
for i in val:
if i['id']==keeps[key]:
final_list.append(i)
請注意,由於列表推導的迭代已在C中執行,因此它比常規python循環和pythonic方式更快。 但如果性能對您不重要,您可以使用常規方法。
你幾乎是在正確的軌道上有一個默認的...這里大致是我會寫它的方式。
from collections import defaultdict
a = [{'un': 'a', 'id': "cd"}, {'un': 'b', 'id': "cd"},{'un': 'b', 'id': "cd"}, {'un': 'c', 'id': "vd"}, {'un': 'c', 'id': "a"}, {'un': 'c', 'id': "vd"}, {'un': 'a', 'id': "cm"}]
items = defaultdict(list)
for row in a:
items[row['un']].append(row['id']) #make a list of 'id' values for each 'un' key
for key in items.keys():
if len(items[key]) > 1: #if there is more than one 'id'
newValue = somefunc(items[key]) #decided which of the list items to keep
items[key] = newValue #put that new value back into the dictionary
以前的答案不適用於字典有兩個以上項目的列表(即它們只保留最多兩個鍵值對 -如果想要保留所有鍵值對,但刪除那些特定鍵被復制? )
為避免將新項目添加到一個特定鍵重復的字典列表中,您可以執行以下操作:
import pandas as pd
all = [
{"email":"art@art.com", "dn":"Art", "pid":11293849},
{"email":"bob@bob.com", "dn":"Bob", "pid":12973129},
{"email":"art@art.com", "dn":"Art", "pid":43975349},
{"email":"sam@sam.com", "dn":"Sam", "pid":92379234},
]
df = pd.DataFrame(all)
df.drop_duplicates(subset=['email'], keep='last', inplace=True)
all = df.to_dict("records")
print(all)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.