0

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

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

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 中的字典之间相交的键。

4

3 回答 3

1

Python 2.x 中的keys方法创建了一个包含所有键副本的列表,并且您不仅为每个 dict 执行此list1操作(可能没什么大不了的,但如果不知道您的数据就很难确定) ,但也dict1一遍又一遍地这样做。

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

两者keys实际上都是完全没有必要的——迭代 dict 会按顺序为您提供键(未指定的顺序,但调用 dict 也是如此keys()),并且in-检查 dict 会搜索与 . 相同的键keys()。因此,仅删除它们会做同样的事情,但更简单、更快,并且使用的内存更少。所以:

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
于 2013-10-03T19:56:42.087 回答
1

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

resultDict = {}

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

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

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都完全相同,因此在这种情况下不会产生任何赔率。

如果您想要每个字典单独的字典 in 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
于 2013-10-03T20:03:01.590 回答
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          
于 2013-10-03T20:03:21.230 回答