-1
votes

Supprimer le dict en double en fonction de la clé et de la valeur de dict

J'ai une structure de données:

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)

Je veux vérifier si la clé et la valeur de la clé sont des doublons, je vais la supprimer. Si la clé et la valeur ont de nombreuses valeurs différentes, je les combinerai.

J'espère que mon résultat ressemble à:

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

Voici mon code:

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

Mais mon résultat est faux (mon résultat est le même avec les correspondances de données). Je ne sais pas pourquoi mon résultat est faux.


2 commentaires

Pourquoi 15477084 a- 15477084 -il [1,2,3] au lieu de [1,1,3,4] ? Pour votre code, vous newdict dict newdict vide à chaque itération, donc if key in newdict.keys() sera toujours False , et ne différera donc pas de l'entrée d'origine.


@Chris J'ai essayé la position newdict dehors de la boucle for j in matches mais cela ne fonctionne pas. Je veux supprimer les doublons de valeur en fonction de la clé, donc 15477084 doit avoir [1,3,4]


6 Réponses :


0
votes

Vous pouvez essayer ceci:

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

production:

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)


0 commentaires

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

4 commentaires

Merci pour votre solution, mais je veux 15477084 avait des valeurs [1,3,4] Je veux supprimer les doublons


Vous pouvez modifier la sortie finale comme cette print([{k: list(set(v))} for k, v in result.items()]) ou utiliser un set dans le defaultdict comme d'autres l'ont fait.


Pouvez-vous m'expliquer pourquoi vous ajoutez {k: list(set(v))} , les données supprimeront les doublons? Je suis un débutant avec python de compréhension. Désolé si ma question vous rend ennuyeux


La fonction set() convertit vos données en un ensemble qui ne contiendra que des éléments uniques (vous avez raison, pas de doublons) et la fonction list() les reconvertira en liste.



1
votes

Essaye ça:

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

Production:

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)


3 commentaires

merci beaucoup, mais dans `res = {k: list (chain (* v)) pour k, v dans res.items ()} je ne comprends pas pourquoi vous faites ça. Peux-tu m'expliquer


valeurs dans res dict est la liste des listes que je fais un lsit plat à partir de cela


Il chain.from_iterable(v) peut-être mieux faire chain.from_iterable(v) au lieu de chain(*v) .



1
votes

Parce que j'aime les pandas, je propose un moyen spécial de résoudre votre problème. Peut-être que vous l'aimerez.

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

C'est le résultat

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)


1 commentaires

C'est la nouvelle solution pour résoudre mes problèmes, merci beaucoup.



0
votes

defaultdict peut vous aider ici

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

Production

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))


0 commentaires

0
votes

Le problème avec votre programme est que newdict sera créé pour chaque itération et qu'il n'aura pas de paires clé-valeur, donc l'instruction (si la clé dans newdict.keys ()) sera toujours fausse, donc sinon l'instruction sera exécutée et il ajoutera le dictionnaire dans la liste des correspondances dans new_matches.

Et aussi l'instruction (si value pas dans newdict [key]), ici value est une liste et newdict [key] sera aussi une liste (si vous avez résolu le problème mentionné ci-dessus), vous comparez donc deux listes. ie) [1] == [3,4] qui ne sera pas vrai. Au lieu de cela, vous devez itérer chaque valeur de l'une des listes et la comparer avec une autre liste.

J'ai fourni la solution en résolvant les deux problèmes de votre programme.

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)


0 commentaires