2010-09-13 2 views
3

Tenir compte de cette courte liste python de dictionnaires (premier élément dictionnaire est une chaîne, deuxième élément est un objet Widget):Nécessité de supprimer les doublons dans une liste de dictionnaires et de modifier les données pour le double restant (python)

raw_results = 
    [{'src': 'tag', 'widget': <Widget: to complete a form today>}, # dupe 1a 
     {'src': 'tag', 'widget': <Widget: a newspaper>},    # dupe 2a 
     {'src': 'zip', 'widget': <Widget: to complete a form today>}, # dupe 1b 
     {'src': 'zip', 'widget': <Widget: the new Jack Johnson album>}, 
     {'src': 'zip', 'widget': <Widget: a newspaper>},    # dupe 2b 
     {'src': 'zip', 'widget': <Widget: premium dog food >}] 

Je veux passer par cette liste et supprimer les doublons qui cette question SO répondues pour moi:

Remove duplicates in a list while keeping its order (Python)

known_widgets= set() 
    processed_results = [] 

    for x in raw_results: 
     widget = x['widget'] 
     if widget in known_widgets: 
      continue 
     else: 
      processed_results.append(x) 
      known_widgets.add(widget) 

Cependant, après Je supprime la ligne en double (par ex. dupe 1b), je veux changer les données "src" du doublon restant (par exemple dupe 1a). Je voudrais ajouter les doublons supprimés "src" à l'original. Voilà ce que je voudrais terminer par:

processed_results = 
    [{'src': 'tag-zip', 'widget': <Widget: to complete a form today>}, # dupe 1a 
    {'src': 'tag-zip', 'widget': <Widget: a newspaper>},    # dupe 2a 
    {'src': 'zip', 'widget': <Widget: the new Jack Johnson album>}, 
    {'src': 'zip', 'widget': <Widget: premium dog food >}] 

Je suis sûr que cela est facile à faire, mais ma tête tourne après trop de café et de nombreuses heures encerclant ce problème. J'aimerais et apprécie vraiment l'aide d'un expert. Je vous remercie!

+0

Vous ne supprimez pas les doublons, vous les fusionnez. Droite? –

+0

Oui, je suppose que c'est plus précis puisque je fusionne les deux champs 'src' des doublons. – mitchf

+0

Vous fusionnez sur src - regroupant tous les src = 'tag-zip' dans un groupe, tous src = 'zip' dans un autre groupe? – hughdbrown

Répondre

2
def find_widget(widget, L): 
    for i, v in enumerate(L): 
     if v[widget] == widget: 
      return i 

known_widgets= set() 
processed_results = [] 

for x in raw_results: 
    widget = x['widget'] 
    if widget in known_widgets: 
     processed_widgets[find_widget(widget, processed_results)]['src'] += '-%s' % x['tag'] 
     continue 
    else: 
     processed_results.append(x) 
     known_widgets.add(widget) 

Peut probablement être fait mieux (car il s'agit de deux passes pour chaque widget en double).

+0

Merci pour l'aide ikanobori, j'apprécie! – mitchf

+0

Si cela fonctionne, pourriez-vous accepter mon message comme réponse en cliquant sur le truc V à gauche de celui-ci? – ikanobori

1

En supposant que vous voulez avoir une liste des widgets calée sur les valeurs Src répétées, c'est ce que vous voulez:

class Widget(object): 
    def __init__(self, desc): 
     self.desc = desc 
    def __str__(self): 
     return "Widget(%s)" % self.desc 

raw_results = [ 
    {'src':'tag-zip', 'widget':Widget('to complete a form today')}, 
    {'src':'tag-zip', 'widget':Widget('a newspaper')}, 
    {'src':'zip', 'widget':Widget('the new Jack Johnson album')}, 
    {'src':'zip', 'widget':Widget('premium dog food')} 
] 

from collections import defaultdict 
known_widgets = defaultdict(list) 
for x in raw_results: 
    k, v = x['src'], x['widget'] 
    known_widgets[k].append(v) 

for k, v in known_widgets.iteritems(): 
    print "%s: %s" % (k, ",".join(str(w) for w in v)) 

Et si vous voulez que les widget5s en double éliminé, faites ceci:

class Widget(object): 
    def __init__(self, desc): 
     self.desc = desc 
    def __str__(self): 
     return "Widget(%s)" % self.desc 
    def __hash__(self): 
     return hash(self.desc) 
    def __cmp__(self, other): 
     return cmp(self.desc, other.desc) 

raw_results = [ 
    {'src':'tag-zip', 'widget':Widget('to complete a form today')}, 
    {'src':'tag-zip', 'widget':Widget('a newspaper')}, 
    {'src':'zip', 'widget':Widget('the new Jack Johnson album')}, 
    {'src':'zip', 'widget':Widget('premium dog food')}, 
    {'src':'tag-zip', 'widget':Widget('to complete a form today')}, 
    {'src':'tag-zip', 'widget':Widget('a newspaper')}, 
    {'src':'zip', 'widget':Widget('the new Jack Johnson album')}, 
    {'src':'zip', 'widget':Widget('premium dog food')}, 
] 

from collections import defaultdict 
known_widgets = defaultdict(set) 
for x in raw_results: 
    k, v = x['src'], x['widget'] 
    known_widgets[k].add(v) 

for k, v in known_widgets.iteritems(): 
    print "%s: %s" % (k, ",".join(str(w) for w in v)) 
Questions connexes