将词典列表与另一个词典相结合

时间:2013-10-03 19:41:21

标签: python list dictionary

我有一个列表,其中包含一定数量的词典,我必须将其与另一个词典进行比较。

它们具有以下形式(键和值没有特定的形式或模式,这些是随机选择的示例):

list1 = [
    {'X1': 'Q587', 'X2': 'Q67G7', ...},
    {'AB1': 'P5K7', 'CB2': 'P678', ...},
    {'B1': 'P6H78', 'C2': 'BAA5', ...}]

dict1 = {
    'X1': set([B00001,B00020,B00010]),
    'AB1': set([B00001,B00007,B00003]), 
    'C2': set([B00001,B00002,B00003]),  ...
}

我现在想要的是一个新词典,其中包含以下键:list1中词典的值。以及dict1的值作为值。只有当键在比较的词典中相交时才会这样。

我已通过以下方式完成此操作:

nDicts = len(list1)
resultDict = {}

    for key in range(0,nDicts):
            for x in list1[key].keys():
                if x in dict1.keys():
                    resultDict.update{list1[key][x]:dict1[x]}
                    print resultDict

所需的输出应采用以下形式:

resulDict = {
        'Q587': set([B00001,B00020,B00010]),
        'P5K7': set([B00001,B00007,B00003]), 
        'BAA5': set([B00001,B00002,B00003]),  ...
    }

这样可行,但由于数据量太高,这需要永远。 有更好的方法吗?

编辑:我稍微更改了输入值,唯一重要的是在list1中的字典和dict1中的字典之间相交的键。

3 个答案:

答案 0 :(得分:1)

Python 2.x中的keys方法创建了一个包含所有键的副本的列表,并且您不仅对list1中的每个词都执行此操作(可能不是什么大不了的事) ,但是在不知道你的数据的情况下很难确定,但也一遍又一遍地为dict1做这件事。

最重要的是,对列表进行in测试需要很长时间,因为它必须检查列表中的每个值,直到找到匹配项,但是对in进行keys测试字典几乎是即时的,因为它只需要查找哈希值。

两个keys()实际上是完全不必要的 - 迭代dict按顺序为你提供键(一个未指定的顺序,但调用in时也是如此)和keys() - 检查dict搜索for key in range(0,nDicts): for x in list1[key]: if x in dict1: resultDict={list1[key][x]:dict1[x]} print resultDict 获得的相同密钥。因此,删除它们会做同样的事情,但更简单,更快速,并且使用的内存更少。所以:

list1

还有一些方法可以简化这一点,可能无法帮助提高性能,但仍然值得做。

您可以直接在for list1_dict in list1: for x in list1_dict: if x in dict1: resultDict = {list_dict[x]: dict1[x]} print resultDict 上进行迭代,而不是构建所有索引的大量列表并迭代它。

for list1_dict in list1:
    for k, v in list1_dict.iteritems():
        if k in dict1:
            resultDict = {v: dict1[k]}
            print resultDict

您只需一步即可获得密钥和值:

for list1_dict in list1:
    for k, v in list1_dict.iteritems():
        try:
            resultDict = {v: dict1[k]}
            print resultDict
        except KeyError:
            pass

此外,如果您希望找到大多数值,首先检查该值需要大约两倍的时间,然后查找它,因为它只是尝试查找并处理失败。 (但是,如果找不到大多数值 ,则情况并非如此。)所以:

{{1}}

答案 1 :(得分:1)

您可以使用设置的交叉点简化和优化您的操作;从Python 2.7开始,字典可以使用dict.viewkeys()方法将键表示为集合,或者在Python 3中表示dict.keys()

resultDict = {}

for d in list1:
    for sharedkey in d.viewkeys() & dict1:
        resultDict[d[sharedkey]] = dict1[sharedkey]

这甚至可以变成一个词典理解:

resultDict = {d[sharedkey]: dict1[sharedkey] 
              for d in list1 for sharedkey in d.viewkeys() & dict1}

我假设你想要一个结果字典,而不是每个共享密钥的新字典。

示例输入演示:

>>> list1 = [
...     {'X1': 'AAA1', 'X2': 'BAA5'},
...     {'AB1': 'AAA1', 'CB2': 'BAA5'},
...     {'B1': 'AAA1', 'C2': 'BAA5'},
... ]
>>> dict1 = {
...     'X1': set(['B00001', 'B00002', 'B00003']),
...     'AB1': set(['B00001', 'B00002', 'B00003']),
... }
>>> {d[sharedkey]: dict1[sharedkey] 
...  for d in list1 for sharedkey in d.viewkeys() & dict1}
{'AAA1': set(['B00001', 'B00002', 'B00003'])}

请注意,X1 AB1都与list1中的词典共享,但在这两种情况下,生成的密钥都为AAA1。其中只有一个获胜(最后一场比赛),但由于dict1中的两个值完全相同,因此在这种情况下不会产生任何赔率。

如果您想在list1中为每个字典添加单独的词典,只需将for d in list1:循环移出:

for d in list1:
    resultDict = {d[sharedkey]: dict1[sharedkey] for sharedkey in d.viewkeys() & dict1}
    if resultDict:  # can be empty
        print resultDict

如果您真的想要每个共享密钥使用一个字典,请移出另一个循环:

for d in list1:
    for sharedkey in d.viewkeys() & dict1:
        resultDict = {d[sharedkey]: dict1[sharedkey]}
        print resultDict

答案 2 :(得分:0)

#!/usr/bin/env python

list1 = [

    {'X1': 'AAA1', 'X2': 'BAA5'},
    {'AB1': 'AAA1', 'CB2': 'BAA5'},
    {'B1': 'AAA1', 'C2': 'BAA5'}

    ]


dict1 = {
    'X1': set(['B00001','B00002','B00003']),
    'AB1': set(['B00001','B00002','B00003'])
}    


g = ( k.iteritems() for k in list1)
ite = ((a,b) for i in g for a,b in i if dict1.has_key(a))

d = dict(ite)            
print d