dictのキーと値に基づいて重複するdictを削除します

2020-06-30 python python-3.x list dictionary duplicates

構造データがあります:

matches = [
                {
                    "15477084": [1]
                },
                {
                    "360418": [2]
                },
                {
                    "15477084": [1]
                },
                {
                    "15477084": [3,4]
                }
            ]

キーとキーの値が重複しているかどうかを確認したいので、削除します。キーと値に多くの異なる値がある場合、それを結合します。

私の結果が次のようになることを願っています:

matches = [
                {
                    "15477084": [1,2,3]
                },
                {
                    "360418": [2]
                }
            ]

これは私のコードです:

new_matches = []

for j in matches:
    newdict = dict()
    for key,value in j.items():
        if key in newdict.keys():
            if value not in newdict[key]:
                newdict[key].append(value)
                new_matches.append(newdict)
        else:
            newdict[key] = value
            new_matches.append(newdict)

しかし、私の結果は間違っています(データの一致と同じ結果が始まります)。私の結果が間違っている理由はありません。

Answers

あなたはこれを試すことができます:

from collections import defaultdict

v = defaultdict(set)

for dict_values in matches:
    for key, value in sorted(dict_values.items()):
        print(key)
        for i in value:
            v[key].add(i)

出力:

defaultdict(set, {'15477084': {1, 3, 4}, '360418': {2}})
from collections import defaultdict

result = defaultdict(list)
for item in matches:
    for k, v in item.items():
        result[k] += v

print([{k: v} for k, v in result.items()])

出力:

[{'15477084': [1, 1, 3, 4]}, {'360418': [2]}]

編集:最終的な出力を一意にするには:

print([{k: list(set(v))} for k, v in result.items()])

これを試して:

from collections import defaultdict
from itertools import chain

res = defaultdict(list)

for x in matches:
    (k,) = x
    if x[k] not in res[k]:
        res[k].append(x[k])

res = {k: list(chain(*v)) for k, v in res.items()}
print(res)

出力:

{'15477084': [1, 3, 4], '360418': [2]}

私はパンダが好きなので、あなたの問題を解決する特別な方法を提供します。あなたはそれを好きになるかもしれません。

import json
import pandas as pd


if __name__ == "__main__":
    matches = [
        {"15477084": [1]},
        {"360418": [2]},
        {"15477084": [1]},
        {"15477084": [3, 4]},
    ]
    matches_df = pd.DataFrame(matches)
    matches_df = matches_df.fillna("[]").transpose().astype(str).apply(
        lambda x: list(
            set([record for sub in x.tolist() for record in json.loads(sub)])
        ),
        axis=1,
    )
    result = matches_df.to_dict()
    print(result)

これが結果です

{'15477084': [1, 3, 4], '360418': [2]}

defaultdictはここで役立ちます

from collections import defaultdict

res_matches = defaultdict(list)
for i in matches:
    key, value = list(i.keys())[0], list(i.values())[0]
    to_add = set(value).difference(set(res_matches[key]))
    if to_add:
        res_matches[key].extend(to_add)
print(dict(res_matches))

出力

{'15477084': [1, 3, 4], '360418': [2]}

プログラムの問題は、newdictがすべての反復で作成され、キーと値のペアがないため、ステートメント(newdict.keys()のキーの場合)が常にfalseになるため、elseステートメントが実行され、一致リストの辞書をnew_matchesに追加します。

また、ステートメント(値がnewdict [key]にない場合)、ここで値はリストであり、newdict [key]もリストになります(上記の問題を解決した場合)、2つのリストを比較します。 ie)[1] == [3,4]これは正しくありません。代わりに、リストのいずれか1つにあるすべての値を反復処理して、別のリストと比較する必要があります。

私は、プログラムの2つの問題を解決することにより、解決策を提供しました。

matches = [
                {
                    "15477084": [1]
                },
                {
                    "360418": [2]
                },
                {
                    "15477084": [1]
                },
                {
                    "15477084": [3,4]
                }
            ]
            
            
new_matches = []

for j in matches:
    newdict = dict()
    for key,value in j.items():
        if len(new_matches) != 0:
            for k in new_matches:
                if key in k.keys():
                    for i in value:
                        if i not in k[key]:
                            k[key].append(i)
                    break

                else:
                    newdict[key] = value
                    new_matches.append(newdict)                 
        else:
            newdict[key] = value
            new_matches.append(newdict)

print(new_matches)

Related