Необходимо удалить дубликаты из списка словарей и изменить данные для оставшегося дубликата (python) - PullRequest
3 голосов
/ 14 сентября 2010

Рассмотрим этот короткий список словарей python (первый элемент словаря - строка, второй элемент - объект Widget):

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 >}]

Я хочу просмотреть этот список и удалить дубликаты, на которые мне так ответил этот вопрос:

Удалить дубликаты в списке, сохраняя его порядок (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)

Однако после того, как я удалю дублирующую строку (например, dupe 1b), я хочу изменить оставшиеся дубликаты (например, dupe 1a) данных "src". Я хотел бы добавить удаленные дубликаты "src" к оригиналу. Вот что я хотел бы закончить:

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 >}]

Я уверен, что это легко сделать, но моя голова кружится после слишком большого количества кофе и многих часов, обходящих эту проблему. Я хотел бы и действительно ценю помощь эксперта. Спасибо!

Ответы [ 2 ]

2 голосов
/ 14 сентября 2010
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)

Возможно, это можно сделать лучше (так как это два прохода для каждого дублирующего виджета).

1 голос
/ 15 сентября 2010

Предполагая, что вы хотите, чтобы список виджетов был связан с повторяющимися значениями src, это то, что вам нужно:

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

И если вы хотите удалить дубликаты widget5s, сделайте следующее:

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