2017-04-08 81 views
-2

我有一個字典的列表,這些字典有另一個嵌套字典。下面是一個例子:刪除字典列表中重複值的最佳方法?

reports = [ 
      {'00T2A00003mDvq9': {'subject': 'dupe1', 'due_date': '4/5/2017'}} 
      {'00T2A00003mDvq8': {'subject': 'dupe2', 'due_date': '4/7/2017'}} 
      {'00T2A00003mDvq7': {'subject': 'dupe1', 'due_date': '4/3/2017'}} 
      ] 

因此,列表中的每個字典都有一個唯一的id和與其相關的值。

我需要一種方法,通過這些字典迭代,並與最新日期,如果任何人有在'subject'場那麼我想刪除完全匹配/刪除整個字典。

因此,使用上面的例子,在遍歷列表和重複刪除之後,我需要結果如下所示。

reports = [ 
      {'00T2A00003mDvq8': {'subject': 'dupe2', 'due_date': '4/7/2017'}} 
      {'00T2A00003mDvq9': {'subject': 'dupe1', 'due_date': '4/3/2017'}} 
      ] 

它刪除'dupe1'的第一個實例,因爲它是更晚的日期。

+2

你有什麼試過,究竟是什麼問題呢? – jonrsharpe

+0

我見過幾個迭代雖然列表的字典,但沒有像上面的嵌套字典。 – bbennett36

+1

這不是我所問的; SO不是代碼編寫服務,您需要自己爲實際實現付出一些努力。另外,請不要恢復合法編輯;每次詢問**一個問題**(最好在閱讀[問]之後)。 – jonrsharpe

回答

1

問題變得更加困難,因爲您不知道reports中字典的鍵值(唯一標識符)。由於每一個都只包含一個項目,因此可以使用next(iter(dict.values()))和Python 3來獲取與它關聯的單個嵌套字典 - 我在下面的代碼中調用checkout來給它起個名字。

鑑於這種情況,我會用會的辦法,首先創建一個字典,組reports元素的主題,然後讓你像這樣用(注工作:我改變了樣品reports數據,以便第一有不止一個具有重複'subject'):

{ 
    'dupe1': [ 
     {'00T2A00003mDvq9': {'due_date': '4/5/2017', 'subject': 'dupe1'}}, 
     {'00T2A00003mDvq7': {'due_date': '4/3/2017', 'subject': 'dupe1'}}, 
     {'00T2A00003mDvq6': {'due_date': '4/6/2017', 'subject': 'dupe1'}} 
    ], 
    'dupe2': [ 
     {'00T2A00003mDvq8': {'due_date': '4/7/2017', 'subject': 'dupe2'}} 
    ] 
} 

與每個主題相關報告的列表然後可以按日期(使用排序基於相同next(iter(dict.values()))絕招lambda),並考慮到現在訂購內容,很容易更新列表並刪除任何杜根據你的願望進行折磨。

from time import strptime 
from pprint import pprint 

DATE_FMT = '%m/%d/%Y' 
reports = [ 
    {'00T2A00003mDvq9': {'subject': 'dupe1', 'due_date': '4/5/2017'}}, 
    {'00T2A00003mDvq8': {'subject': 'dupe2', 'due_date': '4/7/2017'}}, 
    {'00T2A00003mDvq7': {'subject': 'dupe1', 'due_date': '4/3/2017'}}, 
    {'00T2A00003mDvq6': {'subject': 'dupe1', 'due_date': '4/6/2017'}}, # + a third duplicate 
] 

by_subject = {} 
for report in reports: 
    checkout = next(iter(report.values())) # get single subdictionary in each dictionary 
    by_subject.setdefault(checkout['subject'], []).append(report) 

for records in by_subject.values(): 
    records.sort(key=lambda rpt: strptime(next(iter(rpt.values()))['due_date'], DATE_FMT)) 

# Update reports list in-place. 
del reports[:] 
for subject, records in by_subject.items(): 
    reports.append(records[0]) # only keep oldest (deletes all newer than first) 

print('Deduped reports:') 
pprint(reports) 

輸出:

Deduped reports: 
[{'00T2A00003mDvq7': {'due_date': '4/3/2017', 'subject': 'dupe1'}}, 
{'00T2A00003mDvq8': {'due_date': '4/7/2017', 'subject': 'dupe2'}}] 
+0

這幾乎可以工作,並且正朝着正確的方向前進。一個問題是我可以有很多副本,這個只會刪除1.另外,我不需要保留重複報告。希望保留原始列表減去重複項。 – bbennett36

+0

你的問題說:「我想刪除/刪除**整個字典與最新日期」(強調我的),這似乎表明刪除只有一個。無論如何,我已根據您的反饋(我認爲)更新了我的答案。 – martineau

+0

我發佈了我的最終解決方案。我認爲你的工作並不完全,因爲我使用python3,但它幾乎就是你的答案。謝謝! – bbennett36

3

既然你完全卡住了,這是一個開始。一個問題是,對於每個dict,密鑰是不同的和未知的。它看起來像只有一個在每個字典對,這樣你就可以得到items()和佔據第一位:

reports = [ 
    {'00T2A00003mDvq9': {'subject': 'dupe1', 'due_date': '4/5/2017'}}, 
    {'00T2A00003mDvq8': {'subject': 'dupe2', 'due_date': '4/7/2017'}}, 
    {'00T2A00003mDvq7': {'subject': 'dupe1', 'due_date': '4/3/2017'}} 
] 

def get_subject(some_dict): 
    return list(some_dict.items())[0][1]['subject'] 

reports.sort(key=get_subject) 
print(reports) 
# [{'00T2A00003mDvq9': {'due_date': '4/5/2017', 'subject': 'dupe1'}}, {'00T2A00003mDvq7': {'due_date': '4/3/2017', 'subject': 'dupe1'}}, {'00T2A00003mDvq8': {'due_date': '4/7/2017', 'subject': 'dupe2'}}] 

reports現在是按主題排序。然後您可以使用groupby獲取按主題分組的報告。

對於每個組,您可以再次使用sort,這次使用due_date。不過,您必須小心,無法按字母順序排序日期,您需要按此順序提取year,month,day或將字符串轉換爲datetime對象,並使用strptime

一旦您的結果按subject分組並按due_date排序,只需獲取每個組的第一個元素即可。完成!

+1

此外,使用日期時間進行日期排序是一個不錯的主意,而不是重新實現輪子。 [你可以將日期時間寫入字符串,並在需要時再次解析它們給日期時間對象。](http://stackoverflow.com/questions/466345/converting-string-into-datetime)。 –

0

這是我去的最終解決方案。基於@ martineau的答案,但我猜測它只是因爲即時通訊使用Python3。

from time import strptime 

DATE_FMT = '%m/%d/%Y' 
reports = [ 
    {'00T2A00003mDvq9': {'subject': 'dupe1', 'due_date': '4/5/2017'}}, 
    {'00T2A00003mDvq8': {'subject': 'dupe2', 'due_date': '4/7/2017'}}, 
    {'00T2A00003mDvq7': {'subject': 'dupe1', 'due_date': '4/3/2017'}}, 
    {'00T2A00003mDvq6': {'subject': 'dupe1', 'due_date': '4/6/2017'}}, # + third duplicate 
] 

DATE_FMT = '%m/%d/%Y' 

    by_subject = {} 
    for report in reports: 
     topic = list(report.values())[0] 
     # assuming only one element in each dictionary 
     by_subject.setdefault(topic['subject'], []).append(report) 

    for records in by_subject.values(): 
     records.sort(key=lambda rec: strptime(list(rec.values())[0]['due_date'], DATE_FMT)) 

    reports = [] 

    for subject, records in by_subject.items(): 

     if len(records) > 1: 
      while len(records) != 1: 
       del records[-1] 
     reports.extend(records) 
相關問題