2017-04-08 11 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はコード作成サービスではありませんので、あなた自身が実際の実装に少しでも力を入れることが期待されます。さらに、正当な編集を元に戻さないでください。 **一度に**一つの質問**を聞いてください(できれば[ask]を読んでから)。 – jonrsharpe

答えて

1

reportsの辞書のキー値(ユニークID)がわからないため、この問題はより困難になります。それぞれが1つのアイテムだけで構成されているので、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を使用して日付()でソートされ、今注文与えることができますその内容を簡単にリストを更新し、任意のduを削除するあなたの欲望に応じてplicates。

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つの問題は、私は多くの重複を持つことができる、これは1つだけを削除することです。また、私は重複していないレポートを保持する必要はありません。元のリストから複製を差し引いたままにする。 – bbennett36

+0

あなたの質問は、 "私は削除/削除**最新の日付を持つ**完全なdict"(強調鉱山)は、1つだけ削除を示すようだ。それにもかかわらず、私はあなたのフィードバックに基づいて私の答えを更新しました。 – martineau

+0

私は最終的な解決策を投稿しました。私はpython3を使用しているので、あなたのことは十分に機能していないと思うが、ほとんどあなたの答えだ。ありがとうございました! – bbennett36

3

あなたは完全に立ち往生しているので、ここでは始まります。 1つの問題は、各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を抽出するか、文字列をstrptimeというdatetimeオブジェクトに変換する必要があります。

結果がsubjectでグループ化され、due_dateでソートされたら、各グループの最初の要素を取得します。完了!

+1

また、ホイールを再実装するのではなく、日付ソートにdatetimeを使用することをお勧めします。 [datetimesを文字列に書いて、必要に応じてdatetimeオブジェクトに再度解析することができます。](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) 
関連する問題