IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

[debutant]: supprimer doublon dans grande liste de dictionnaire [Python 3.X]


Sujet :

Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2017
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2017
    Messages : 32
    Par défaut [debutant]: supprimer doublon dans grande liste de dictionnaire
    Bonjour à Tous & Toutes
    J'ai une énorme liste de dictionnaire, avec des doublons.
    Je n'arrive pas à supprimer ces doublons avec la technique de créér une nouvelle liste et d'ajouter les éléments 1 à 1. Cela ne renvoie pas d'erreurs mais cela tourne sans donner de résultats.
    Connaissez-vous une méthode efficace?
    Merci

  2. #2
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Il est difficile de proposer quelque chose en en connaissant aussi peu. Donne un petit exemple (même avec des données bidons si c'est confidentiel) de tes données avec les doublons que tu cherches à éliminer. Et montre le code que tu as fait et qui ne marche pas.

  3. #3
    Membre Expert

    Homme Profil pro
    Ingénieur calcul scientifique
    Inscrit en
    Mars 2013
    Messages
    1 229
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Alpes Maritimes (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur calcul scientifique

    Informations forums :
    Inscription : Mars 2013
    Messages : 1 229
    Par défaut
    Oui il faut montrer le code, et un exemple de données même petite (et tu nous en donnes la taille après dans ton message). Comme ca ca nous permet déjà de voir si c'est un souci de code ou juste un problème d'optimisation de celui ci, et on peut avoir une base sur laquelle réfléchir de notre côté.

  4. #4
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2017
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2017
    Messages : 32
    Par défaut
    Bonjour,

    merci pour vos réponses, la liste est stockée dans un fichier pickle qui fait 38 Mo et comporte 97000 éléments.
    Sa structure ressemble à ça : 3 clés pour le dixtionnaire mais un set de taille indéfininie pour chaque clé:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    [{"k1": {"truc","bidule"}, "k2" : {"machin","blaba"}, "k3" : {'xx',"yyy","zz"}},
    {"k1": {"truc2","bidule2"}, "k2" : {"machin2","blaba2"}, "k3" : {'xx2',"yyy2","zz2"}},
    {"k1": {"truc","bidule"}, "k2" : {"machin","blaba"}, "k3" : {'xx',"yyy","zz"}},   # doublon à supprimer
    ]
    le code testé :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    new_d = []
    for element in old_d:
        if element not in new_d:
            new_d.append(element)
    La liste est trop grande donc ça tourne, ça tourne, mais pas de résultat

    Merci pour vos idées !

  5. #5
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 332
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 332
    Par défaut
    bonjour

    pourquoi ne pas tester ce code que tu nous donnes ???

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    elements = [
        {"k1": {"truc","bidule"}, "k2" : {"machin","blaba"}, "k3" : {'xx',"yyy","zz"}},
        {"k1": {"truc2","bidule2"}, "k2" : {"machin2","blaba2"}, "k3" : {'xx2',"yyy2","zz2"}},
        {"k1": {"truc","bidule"}, "k2" : {"machin","blaba"}, "k3" : {'xx',"yyy","zz"}},   # doublon à supprimer
    ]
    print(elements)
    nouveaux = []
    for element in elements:
        print("origin", element)
        if element not in nouveaux:
            nouveaux.append(element)
    print("")
    for element in nouveaux:
        print("nouveau", element)

  6. #6
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2017
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2017
    Messages : 32
    Par défaut
    j'ai testé hier mais rien de sortait comme résultat donc je ne sais pas combien de temps (d'heures ??) cela va prendre, c'est pour ça que je me suis dit qu'il devait y avoir des méthodes plus efficaces

  7. #7
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 790
    Par défaut
    Citation Envoyé par gingko41 Voir le message
    La liste est trop grande donc ça tourne, ça tourne, mais pas de résultat
    Ben ouais mais un code qui fonctionne bien pour des listes à quelques items ne sont pas adaptés à toutes tailles... ça dépend de leur complexité algorithmique.

    Comme comparer des dictionnaires se réduit à '==' (pas de relation d'ordre...), il va peut être falloir trouver une structure de données intermédiaire pour y arriver... mais le forum algo. est là pour çà.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  8. #8
    Expert confirmé Avatar de papajoker
    Homme Profil pro
    Développeur Web
    Inscrit en
    Septembre 2013
    Messages
    2 332
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Nièvre (Bourgogne)

    Informations professionnelles :
    Activité : Développeur Web
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Septembre 2013
    Messages : 2 332
    Par défaut
    Tu peux aussi essayer un dictionnaire ? on passe en index la ligne transformée en chaine (possible d'utiliser autre chose que str()..., c'est l'idée)
    cela évite le if element not in, donc on ne parcourt pas une liste dans une boucle
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    defaut = [
        {"k1": {"truc","bidule"}, "k2" : {"machin","blaba"}, "k3" : {'xx',"yyy","zz"}},
        {"k1": {"truc2","bidule2"}, "k2" : {"machin2","blaba2"}, "k3" : {'xx2',"yyy2","zz2"}},
        {"k1": {"truc","bidule"}, "k2" : {"machin","blaba"}, "k3" : {'xx',"yyy","zz"}},   # doublon à supprimer
    ]
    elements = []
    for i in range(33000):
        elements.extend(default)
    print(len(elements))
     
    nouveaux = {}
    for element in elements:
        nouveaux[str(element)] = element
     
    for element in nouveaux.values():
        print("nouveau", element)

  9. #9
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 872
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 872
    Billets dans le blog
    1
    Par défaut
    Bonjour
    Citation Envoyé par gingko41 Voir le message
    J'ai une énorme liste de dictionnaire, avec des doublons.
    Déjà il faudrait que tu précises ce que tu entends par "doublon" (surtout entre deux dictionnaires). Ok tu as donné un exemple avec le 3° marqué "doublon" mais un exemple ce n'est pas fait pour remplacer une définition mais pour l'illustrer. Donc même avec exemple, la définition reste impérative.
    D'après cet exemple, un doublon c'est "clefs+valeurs identiques" c'est ça ???

    Ensuite, tu ne dis pas si tu veux garder l'ordre final identique (sans les doublons) à l'ordre initial, parce que cela a une influence sur l'algo. Si par exemple c'est inutile de garder l'ordre, alors ça devient plus facile
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    pour chaque élément pris dans la liste initiale triée, faire
        si élément identique à élément mémorisé, alors on continue la boucle (on saute la suite du code)
        mémorisation élément en cours
        ajout élément en cours dans la nouvelle liste
    fin faire
    Ce qui donne en Python
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    base=[
    	{"k1": {"truc","bidule"}, "k2" : {"machin","blaba"}, "k3" : {'xx',"yyy","zz"}},
    	{"k1": {"truc2","bidule2"}, "k2" : {"machin2","blaba2"}, "k3" : {'xx2',"yyy2","zz2"}},
    	{"k4": {"truc2","bidule2"}, "k2" : {"machin2","blaba2"}, "k3" : {'xx2',"yyy2","zz2"}},
    	{"k1": {"truc","bidule"}, "k2" : {"machin","blaba"}, "k3" : {'xx',"yyy","zz"}},   # doublon à supprimer
    ]
     
    res=[]
    mem=None
    for item in sorted(base, key=lambda x: tuple(x.keys()) + tuple(x for v in x.values() for x in v)):
    	if item == mem: continue
    	mem=item
    	res.append(item)
     
    for item in res: print(item)
    (ok je l'avoue, j'en ai un peu chié pour trouver le critère de tri, critère que j'ai imaginé finalement comme étant la liste des clefs suivi de la liste de tous les éléments pris à partir des valeurs)
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  10. #10
    Membre averti
    Femme Profil pro
    Étudiant
    Inscrit en
    Janvier 2017
    Messages
    32
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Loir et Cher (Centre)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Janvier 2017
    Messages : 32
    Par défaut
    merci pour vos réponses,

    oui je n'avais pas précisé mais en effet l'ordre n'était pas important dans la liste.
    J'ai utilisé la méthode de sve@r et j'ai bien mon résultat.

    Encore merci à tous et bon we !

  11. #11
    Invité
    Invité(e)
    Par défaut
    En version one-line :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    toto = [{"k1": {"truc","bidule"}, "k2" : {"machin","blaba"}, "k3" : {'xx',"yyy","zz"}},
    {"k1": {"truc2","bidule2"}, "k2" : {"machin2","blaba2"}, "k3" : {'xx2',"yyy2","zz2"}},
    {"k1": {"truc","bidule"}, "k2" : {"machin","blaba"}, "k3" : {'xx',"yyy","zz"}},   # doublon à supprimer
    ]
    import ast
    list(ast.literal_eval(dico) for dico in set([str(dico) for dico in toto]))
    PS : Surement pas performant...

  12. #12
    Membre prolifique
    Avatar de Sve@r
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Février 2006
    Messages
    12 872
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Oise (Picardie)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Février 2006
    Messages : 12 872
    Billets dans le blog
    1
    Par défaut
    J'ai mieux réfléchi à ma clef de tri. Je pense que concaténer les clefs puis les valeurs c'est pas super safe (ça donne k1 : {v1}, k2 {v2} identique à k1 : {}, k2 : {v1, v2} ou à k1 : {v1, ,v2}, k2 : {})
    Je l'ai donc réécrit ainsi: k1 : {v11, v12}, k2 : {v21, v22} donne (lors du tri) (k1, (v11, v12), k2, (v21, v22)).
    Code python : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    for item in sorted(base, key=lambda d: tuple((x[0], tuple(x[1])) for x in d.items())):
    	if item == mem: continue
    	mem=item
    	res.append(item)
    (et en plus ça fait moins de manip dans l'expression)

    Et question performance de la solution one-line, transformer le dico en string pour ensuite le remettre en dico effectivement ça sent pas super bon. Ceci dit, ma méthode qui trie la liste initiale pour regrouper les éléments identiques c'est pas non plus optimum (le tri a un coût) mais de toute façon la complexité est là donc faut choisir: soit on la reporte sur le tri et ensuite le traitement c'est peanut, soit on la reporte dans le traitement. J'ai choisi le tri, présumant que les fonctions natives de Python feraient mieux qu'un algo qui regarderait à chaque itération si l'élément est/n'est pas déjà présent.
    Mon Tutoriel sur la programmation «Python»
    Mon Tutoriel sur la programmation «Shell»
    Sinon il y en a pleins d'autres. N'oubliez pas non plus les différentes faq disponibles sur ce site
    Et on poste ses codes entre balises [code] et [/code]

  13. #13
    Invité
    Invité(e)
    Par défaut
    Ta façon de faire est bien plus rapide 3 µsec contre 47 avec la mienne.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    import ast, time
     
    toto = [{"k1": {"truc","bidule"}, "k2" : {"machin","blaba"}, "k3" : {'xx',"yyy","zz"}},
    {"k1": {"truc2","bidule2"}, "k2" : {"machin2","blaba2"}, "k3" : {'xx2',"yyy2","zz2"}},
    {"k1": {"truc","bidule"}, "k2" : {"machin","blaba"}, "k3" : {'xx',"yyy","zz"}},   # doublon à supprimer
    ]
     
    def test1():
     
        st = time.time()
        list(ast.literal_eval(dico) for dico in set([str(dico) for dico in toto]))
        return time.time()-st
     
    def test2():
     
        st = time.time()
        mem = None
        res = []
        for item in sorted(toto, key=lambda d: tuple((x[0], tuple(x[1])) for x in d.items())):
            if item == mem: continue
            mem=item
            res.append(item)
        return time.time()-st
     
     
    moy1 = int((sum([test1() for _ in range(100000)])/100000)*10**6)
    moy2 = int((sum([test2() for _ in range(100000)])/100000)*10**6)
     
    print(moy1, moy2)

  14. #14
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 790
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 790
    Par défaut
    Salut,

    Citation Envoyé par Sve@r Voir le message
    Je l'ai donc réécrit ainsi: k1 : {v11, v12}, k2 : {v21, v22} donne (lors du tri) (k1, (v11, v12), k2, (v21, v22))
    Il serait moins faux de fabriquer le tuple (ki, vi) ou vi sera le tuple trié du set correspondant. Puis on trie sur les (ki, vi).

    Maintenant, si on reformule, on a 3 colonnes k1, k2, k3... chaque ligne étant composé de 3 set de chaînes de caractères: s1, s2, s3.
    Les dictionnaires et les set ne sont pas ordonnés - les dictionnaires préservent l'ordre d'insertion mais on ne sait pas s'ils ont été "bien" construits -.

    Normalement si on transforme chaque si en tuple trié ti, le tuple de tuples t1, t2, t3 suffit à détecter les doublons et est ordonné alphabétiquement.

    Codé çà donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    base=[
    	{"k1": {"truc","bidule"}, "k2" : {"machin","blaba"}, "k3" : {'xx',"yyy","zz"}},
    	{"k1": {"truc2","bidule2"}, "k2" : {"machin2","blaba2"}, "k3" : {'xx2',"yyy2","zz2"}},
    	{"k1": {"truc2","bidule2"}, "k2" : {"machin2","blaba2"}, "k3" : {'xx2',"yyy2","zz2"}},
    	{"k1": {"truc","bidule"}, "k2" : {"machin","blaba"}, "k3" : {'xx',"yyy","zz"}},   # doublon à supprimer
    ]
    KEYS = 'k1', 'k2', 'k3',
    m = set()
    result = []
    for d in base:
        v = tuple(tuple(sorted(d[k])) for k in KEYS)
        if v not in m:
            m.add(v)
            result.append(d)
    print(m)
    print(result)
    Après tout lire pour trier pour ensuite retirer les doublons ou tester l'existence de la valeur calculée dans un set avant de... c'est à tester avec de vraies données.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [XL-2016] Supprimer doublons dans liste déroulante
    Par Vba14 dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 28/04/2019, 12h47
  2. Supprimer doublons dans une liste
    Par yrmab dans le forum Scheme
    Réponses: 7
    Dernier message: 09/05/2013, 18h14
  3. Supprimer les doublons dans une liste
    Par inforum dans le forum SL & STL
    Réponses: 2
    Dernier message: 22/11/2009, 16h21
  4. [MySQL] Supprimer doublon dans une liste
    Par Gad29 dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 06/06/2007, 15h13
  5. Réponses: 13
    Dernier message: 01/08/2006, 17h59

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo