2010-11-05 7 views
3

Considérez ce format de dictionnaire.Supprimer les doublons du dictionnaire imbriqué, si deux valeurs sont identiques, en Python

{1:{'name':'chrome', 'author':'google', 'url':'http://www.google.com/' }, 
2:{'name':'firefox','author':'mozilla','url':'http://www.mozilla.com/'}} 

Je souhaite supprimer tous les éléments portant le même nom et l'auteur. Je peux facilement supprimer des entrées dupliquées basées sur des clés en plaçant toutes les clés dans un ensemble, et peut-être développer ceci pour travailler sur une valeur spécifique, mais cela semble être une opération coûteuse qui itère plusieurs fois sur un dictionnaire. Je ne saurais pas comment faire cela avec deux valeurs de manière efficace. C'est un dictionnaire avec des milliers d'objets.

+1

Comment faire vous obtenez ces données? Vous pouvez le construire en utilisant une paire de mappage de dictionnaire (nom, auteur) à l'URL en premier lieu, alors il n'y aura pas besoin de faire cela du tout. –

+1

Peut-être juste changer une structure de dict et définir le nom et l'auteur sont la clé de dict? – demas

+0

Je ne l'ai pas mentionné spécifiquement, mais je veux également compter les éléments supprimés pour référence interne, en faisant 'len (dict)' avant et après. Et changer la structure ne fait aucune différence, car j'enlève aussi les clés en double. J'ai un peu simplifié le dictionnaire dans l'exemple. –

Répondre

3

dans le dictionnaire Itérer, garder une trace de rencontre (name, author) tuples que vous allez et supprimer ceux que vous avez déjà rencontré:

def remove_duplicates(d): 
    encountered_entries = set() 
    for key, entry in d.items(): 
     if (entry['name'], entry['author']) in encountered_entries: 
      del d[key] 
     else: 
      encountered_entries.add((entry['name'], entry['author'])) 
+1

Il n'est pas permis de changer un dict en itérant sur 'd.keys()' - cela donne des résultats indéfinis. –

+1

@Sven: Itérer sur 'd.keys()' et changer le dict est correct dans Python 2.5 (dont parle cette question). 'd.keys()' retourne une liste des clés dans le dict, et cette liste n'est pas affectée par une modification ultérieure du dict. Modifier la dict en itérant sur la dict elle-même, ou sur 'd.iterkeys()', 'd.itervalues ​​()' ou 'd.iteritems()' n'est pas correct, cependant. –

+0

@ Pär: Vous avez raison :) J'utilise toujours 'iterkeys()' pour éviter la liste intermédiaire. –

1

Voyons voir si cela fonctionne ...

from itertools import groupby 

def entry_key(entry): 
    key, value = entry 
    return (value['name'], value['author']) 

def nub(d): 
    items = d.items() 
    items.sort(key=entry_key) 
    grouped = groupby(items, entry_key) 
    return dict([grouper.next() for (key, grouper) in grouped]) 
+0

J'ai essayé ceci, mais Python 2.5 n'a pas 'next()'. Peut-être que j'aurais dû mettre ça dans le texte, au lieu de juste une étiquette. –

+0

Oh, d'accord. Utilisez juste .next() alors. – sykora

+0

Merci, cela fonctionne. Cependant, je l'ai profilé et l'autre réponse est environ deux fois plus rapide. –

Questions connexes