簡體   English   中英

在 Python 字典列表中查找重復項

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM