Объедините два словаря и удалите дубликаты в Python - PullRequest
0 голосов
/ 27 марта 2012

Привет, у меня есть два разных словаря. И я пытаюсь объединить эти два, удалив дубликаты. Это 2 списка.

x = [{'relevance': 0.722, 'type': 'Company', 'name': 'Dell'}, {'relevance': 0.314, 'type': 'OperatingSystem', 'name': 'VMs'}, {'relevance': 0.122, 'type': 'Technology', 'name': 'iSCSI'}, {'relevance': 0.266, 'type': 'Company', 'name': 'Force10'}, {'relevance': 0.327, 'type': 'Person', 'name': 'Greg Althaus'}, {'relevance': 0.085, 'type': 'URL', 'name': 'http://Dell.com/OpenStack'}, {'relevance': 0.174, 'type': 'Company', 'name': 'Storage Hardware'}]
y = [{'relevance': u'0.874065', 'type': u'Company', 'name': u'Dell'}, {'relevance': u'0.522169', 'type': u'OperatingSystem', 'name': u'VMs'}, {'relevance': u'0.444586', 'type': u'Person', 'name': u'Rob Hirschfeld'}, {'relevance': u'0.413988', 'type': u'Person', 'name': u'Greg Althaus'}, {'relevance': u'0.376489', 'type': u'FieldTerminology', 'name': u'iSCSI'}, {'relevance': u'0.314059', 'type': u'Company', 'name': u'Force10'}]

Я пытался сделать

z = x.update(y)
print x

Это дало мне эту ошибку

AttributeError: 'str' object has no attribute 'update'`

Я пробовал это

z = dict(x.items() + y.items())

Это дало мне эту ошибку

AttributeError: 'str' object has no attribute 'items'

Тогда я попробовал

z = dict(x, **y)

Это дало мне эту ошибку

TypeError: type object argument after ** must be a mapping, not str

Тогда я попробовал

z = dict(chain(x.iteritems(), y.iteritems()))

Это дало мне эту ошибку

AttributeError: 'str' object has no attribute 'iteritems'

Ответы [ 5 ]

3 голосов
/ 27 марта 2012

Если вы хотите создать новый список словарей и хотите объединить их, удалив дубликаты, это будет просто работать.

def DictListUpdate( lis1, lis2):
    for aLis1 in lis1:
        if aLis1 not in lis2:
            lis2.append(aLis1)
    return lis2

x = [ {"name": "surya", "company":"dell"}, \
       {"name": "jobs", "company":"apple"} ]

y = [ { "name": "surya", "company":"dell"}, \
    { "name": "gates", "company": "microsoft"} ]

print DictListUpdate(x,y)

Вывод:

>>> 
[{'company': 'dell', 'name': 'surya'}, {'company': 'microsoft', 'name': 'gates'}, {'company': 'apple', 'name': 'jobs'}]
3 голосов
/ 27 марта 2012

Вы можете преобразовать списки в строках в dict с ключом по имени, а затем обновить:

import ast

x = "[{'relevance': 0.722, 'type': 'Company', 'name': 'Dell'}, {'relevance': 0.314, 'type': 'OperatingSystem', 'name': 'VMs'}, {'relevance': 0.122, 'type': 'Technology', 'name': 'iSCSI'}, {'relevance': 0.266, 'type': 'Company', 'name': 'Force10'}, {'relevance': 0.327, 'type': 'Person', 'name': 'Greg Althaus'}, {'relevance': 0.085, 'type': 'URL', 'name': 'http://Dell.com/OpenStack'}, {'relevance': 0.174, 'type': 'Company', 'name': 'Storage Hardware'}]"
y = "[{'relevance': u'0.874065', 'type': u'Company', 'name': u'Dell'}, {'relevance': u'0.522169', 'type': u'OperatingSystem', 'name': u'VMs'}, {'relevance': u'0.444586', 'type': u'Person', 'name': u'Rob Hirschfeld'}, {'relevance': u'0.413988', 'type': u'Person', 'name': u'Greg Althaus'}, {'relevance': u'0.376489', 'type': u'FieldTerminology', 'name': u'iSCSI'}, {'relevance': u'0.314059', 'type': u'Company', 'name': u'Force10'}]"

        # make a dictionary with the names as keys
x, y = (dict((d['name'], d) 
            # after loading the lists out of the strings safely
            for d in ast.literal_eval(lst)) 
                  # for each of the two strings
                  for lst in (x, y))
# or on Python 2.7+:
x, y = ({d['name']: d for d in ast.literal_eval(lst)} for lst in (x, y))
# combine the two dicts
x.update(y)

Тогда, если вы хотите вернуть список, это просто

x.values()

Вы упоминаете сортировку в своем заголовке. Если вы хотите отсортировать этот список по имени:

import operator
sorted(x.itervalues(), key = operator.itemgetter('name'))
1 голос
/ 27 марта 2012

Первое, что нужно знать, это то, что у вас нет двух разных словарей.У вас есть два разных списка словарей.Во-вторых, вы не объясняете, что именно считается дубликатом.В-третьих, вы не говорите, что делать с клавишей relevance.

Я предполагаю, что два словаря с эквивалентными ключами type и name идентичны, и что вы хотите, чтобы значения relevance были объединены в список.Затем вы могли бы усреднить их, или что-то еще.

def gen_key(d):
    return (d['name'], d['type'])

def merge_dupes(dlist):
    relevance = [float(d['relevance']) for d in dlist]
    name, type = dlist[0]['name'], dlist[0]['type']
    return {'name':name, 'type':type, 'relevance':relevance}

to_merge = {}
for l in (x, y):
    for d in l:
        to_merge.setdefault(gen_key(d), []).append(d)

# if you want another list
merged_list = [merge_dupes(l) for l in to_merge.itervalues()]

# if you'd prefer a dictionary
merged_dict = dict((k, merge_dupes(v)) for k, v in to_merge.iteritems())

Выход:

>>> pprint(merged_list)
[{'name': u'Rob Hirschfeld',
  'relevance': [0.44458599999999998],
  'type': u'Person'},
 {'name': 'VMs',
  'relevance': [0.314, 0.52216899999999999],
  'type': 'OperatingSystem'},
 {'name': 'Greg Althaus',
  'relevance': [0.32700000000000001, 0.41398800000000002],
  'type': 'Person'},
 {'name': 'Storage Hardware',
  'relevance': [0.17399999999999999],
  'type': 'Company'},
 {'name': u'iSCSI',
  'relevance': [0.37648900000000002],
  'type': u'FieldTerminology'},
 {'name': 'Force10',
  'relevance': [0.26600000000000001, 0.31405899999999998],
  'type': 'Company'},
 {'name': 'http://Dell.com/OpenStack',
  'relevance': [0.085000000000000006],
  'type': 'URL'},
 {'name': 'Dell',
  'relevance': [0.72199999999999998, 0.87406499999999998],
  'type': 'Company'},
 {'name': 'iSCSI', 'relevance': [0.122], 'type': 'Technology'}]
>>> pprint(merged_dict)
{('Dell', 'Company'): {'name': 'Dell',
                       'relevance': [0.72199999999999998,
                                     0.87406499999999998],
                       'type': 'Company'},
 ('Force10', 'Company'): {'name': 'Force10',
                          'relevance': [0.26600000000000001,
                                        0.31405899999999998],
                          'type': 'Company'},
 ('Greg Althaus', 'Person'): {'name': 'Greg Althaus',
                              'relevance': [0.32700000000000001,
                                            0.41398800000000002],
                              'type': 'Person'},
 (u'Rob Hirschfeld', u'Person'): {'name': u'Rob Hirschfeld',
                                  'relevance': [0.44458599999999998],
                                  'type': u'Person'},
 ('Storage Hardware', 'Company'): {'name': 'Storage Hardware',
                                   'relevance': [0.17399999999999999],
                                   'type': 'Company'},
 ('VMs', 'OperatingSystem'): {'name': 'VMs',
                              'relevance': [0.314, 0.52216899999999999],
                              'type': 'OperatingSystem'},
 ('http://Dell.com/OpenStack', 'URL'): {'name': 'http://Dell.com/OpenStack',
                                        'relevance': [0.085000000000000006],
                                        'type': 'URL'},
 (u'iSCSI', u'FieldTerminology'): {'name': u'iSCSI',
                                   'relevance': [0.37648900000000002],
                                   'type': u'FieldTerminology'},
 ('iSCSI', 'Technology'): {'name': 'iSCSI',
                           'relevance': [0.122],
                           'type': 'Technology'}}
1 голос
/ 27 марта 2012

Ваши начальные ошибки приведены потому, что вы определили свой словарь как строку списка словаря. Есть ли конкретные причины этого?

Это будет довольно сложно сделать как строку.

Попробуйте это:

x = [{'relevance': 0.722, 'type': 'Company', 'name': 'Dell'}, {'relevance': 0.314, 'type': 'OperatingSystem', 'name': 'VMs'}, {'relevance': 0.122, 'type': 'Technology', 'name': 'iSCSI'}, {'relevance': 0.266, 'type': 'Company', 'name': 'Force10'}, {'relevance': 0.327, 'type': 'Person', 'name': 'Greg Althaus'}, {'relevance': 0.085, 'type': 'URL', 'name': 'http://Dell.com/OpenStack'}, {'relevance': 0.174, 'type': 'Company', 'name': 'Storage Hardware'}]
y = [{'relevance': u'0.874065', 'type': u'Company', 'name': u'Dell'}, {'relevance': u'0.522169', 'type': u'OperatingSystem', 'name': u'VMs'}, {'relevance': u'0.444586', 'type': u'Person', 'name': u'Rob Hirschfeld'}, {'relevance': u'0.413988', 'type': u'Person', 'name': u'Greg Althaus'}, {'relevance': u'0.376489', 'type': u'FieldTerminology', 'name': u'iSCSI'}, {'relevance': u'0.314059', 'type': u'Company', 'name': u'Force10'}]

z = {}
for dic in x+y:
   z.update(dic)

print dic
0 голосов
/ 28 марта 2012

Спасибо за ответы.Я мог бы получить решение.Извините, что не смог правильно объяснить мои требования.Я хотел удалить дубликаты на основе ключа 'name'.

Я пытался сделать это.Это сработало.

def DictListUpdate( lis1, lis2):
    for aLis1 in lis1:
        if aLis1 not in lis2:
            lis2.append(aLis1)
    return lis2

z = DictListUpdate(x,y)
getvals = operator.itemgetter('name')

z.sort(key=getvals)

result = []
for k, g in itertools.groupby(z, getvals):
    result.append(g.next())

z[:] = result
print(z)

И вывод

[{'name': 'Compute Hardware', 'relevance': '0.236', 'type': 'Company'},
 {'name': 'Dell', 'relevance': '0.874065', 'type': 'Company'},
 {'name': 'Force10', 'relevance': '0.314059', 'type': 'Company'},
 {'name': 'Greg Althaus', 'relevance': '0.413988', 'type': 'Person'},
 {'name': 'Need to administrative infrastructure',
  'relevance': '0.292',
  'type': 'IndustryTerm'},
 {'name': 'Nova Volume', 'relevance': '0.101', 'type': 'Person'},
 {'name': 'RAM', 'relevance': '0.363781', 'type': 'Technology'},
 {'name': 'Rob Hirschfeld', 'relevance': '0.444586', 'type': 'Person'},
 {'name': 'Storage Hardware', 'relevance': '0.174', 'type': 'Company'},
 {'name': 'VMs', 'relevance': '0.522169', 'type': 'OperatingSystem'},
 {'name': 'http://Dell.com/OpenStack', 'relevance': '0.085', 'type': 'URL'},
 {'name': 'http://RobHirschfeld.com', 'relevance': '0.073', 'type': 'URL'},
 {'name': 'iSCSI', 'relevance': '0.376489', 'type': 'FieldTerminology'}]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...