【问题标题】:Combine two dictionaries and remove duplicates in python合并两个字典并在python中删除重复项
【发布时间】:2012-03-27 13:22:02
【问题描述】:

您好,我有两个不同的词典。我正在尝试通过删除重复项来合并这两者。这是 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'

【问题讨论】:

  • 您要删除重复的密钥还是重复的key:value 对?无论如何,如您所见,您声明的是strings,而不是列表,请删除双引号
  • x 和 y 都是字符串,不是字典或列表。
  • 代码缩进四个空格,普通文本不应该缩进。请花点时间确保您的问题格式正确,以便其他人可以阅读并帮助您。
  • xy两个字典有相同的key时,你想保留哪个字典value
  • 您认为错误消息是什么意思?他们对我来说似乎很清楚。您正在使用字符串:'str' object ...

标签: python merge


【解决方案1】:

如果您希望创建一个新的字典列表并希望通过删除重复项来合并它们,这很简单。

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

【讨论】:

  • 嗨,苏里亚,感谢您的回复。我之前已经尝试过了,我已经得到了合并列表。但我不知道如何根据键删除重复项。
  • Surya,我可以根据“名称”键删除重复项。这是代码..'getvals = operator.itemgetter('name') z.sort(key=getvals) result = [] for k, g in itertools.groupby(z, getvals): result.append(g.next ()) z[:] = 结果打印(z)'
【解决方案2】:

你可以将lists-in-strings转换成dicts,然后更新:

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

【讨论】:

    【解决方案3】:

    首先要注意的是,您没有两个不同的字典。您有两个不同的字典列表。第二个是你没有准确解释什么是重复的。三是你不说relevance键怎么办。

    我假设两个具有等效 typename 键的字典是相同的,并且您希望将 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'}}
    

    【讨论】:

      【解决方案4】:

      给出初始错误是因为您已将字典定义为字典列表的字符串。这背后有什么具体原因吗?

      作为一个字符串这样做会相当困难。

      试试这个:

      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
      

      【讨论】:

      • 你试过你的代码了吗?它不会删除重复项,它只是不断写入相同的值,因此您最终得到的只是最后一个字典。
      • 是的,我运行了代码,但作者并没有具体说明他想要做什么。我只是准确地写了他试图做的没有错误的事情。
      • 他认为他有一本字典词典(就像我在代码中创建的那样)。如果他有这个,他的代码肯定会删除重复的,而不是像你那样做。
      • 各位朋友,我有两本来自 2 个不同来源的字典。所以,我需要合并这些字典,同时删除重复项。我已删除双引号并尝试合并,这次我收到此错误“AttributeError:'list' object has no attribute 'items'”
      • @ArjunKumarReddy 您是否在我的答案中运行了代码?它适用于字符串或列表,如果您只需取出 ast.literal_eval(lst) 并将其替换为 lst
      【解决方案5】:

      感谢您的回答。我可以得到解决方案。抱歉,我无法正确解释我的要求。我想根据“名称”键删除重复项。

      我已经尝试过这样做。它奏效了。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-05-25
        • 1970-01-01
        • 2012-09-12
        • 2020-05-20
        • 2015-11-29
        • 2018-06-09
        • 1970-01-01
        • 2017-06-22
        相关资源
        最近更新 更多