python quickest way to merge dictionaries based on key match
我有两本字典。清单A长34000,清单B长650000。我基本上是将所有列表B的dicts插入到列表A的dicts中,它基于一个键匹配。目前,我做的很明显,但它永远(认真地说,就像一天)。一定有更快的方法!
1 2 3 4 5 | for a in listA: a['things'] = [] for b in listB: if a['ID'] == b['ID']: a['things'].append(b) |
1 2 3 4 5 6 7 8 9 | from collections import defaultdict dictB = defaultdict(list) for b in listB: dictB[b['ID']].append(b) for a in listA: a['things'] = [] for b in dictB[a['ID']]: a['things'].append(b) |
这将把您的算法从o(n*m)转换为o(m)+o(n),其中n=len(lista),m=len(listb)
基本上,它避免了通过"预先计算"列表B中的哪些dict与每个"id"匹配来为列表A中的每个dict循环遍历列表B中的每个dict。
这是一个可能有帮助的方法。我会留给你来填写细节。
您的代码很慢,因为它是一个O(n^2)算法,将每个A与每个B进行比较。
如果先按ID对lista和listb中的每一个进行排序(这是o(nlogn))操作,那么您可以轻松地遍历已排序的a和b版本(这将是线性时间)。
这种方法在必须对非常大的数据集进行外部合并时很常见。Mihai的答案更适合内部合并,在这里您只需按ID(内存中)索引所有内容。如果您有足够的内存来保存这些额外的结构,并且字典查找是持续的,那么这种方法可能更快,更不用说更简单了。:)
举例来说,我们假设A在排序后具有以下ID
1 | acfgjp |
B有这些身份证,排序后又有一次
1 | aaaabbbbcccddeeeefffggiikknnnnppppqqqrrr |
奇怪的是,这个想法可以让索引保持在A和B中(我知道这听起来不是很像Python)。首先,你看到的是a中的
我将把lista和listb转换成字典,用i d作为键的字典。然后,使用python的快速字典查找附加数据是一件简单的事情:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | from collections import defaultdict class thingdict(dict): def __init__(self, *args, **kwargs): things = [] super(thingdict,self).__init__(*args, things=things, **kwargs) A = defaultdict(thingdict) A[1] = defaultdict(list) A[2] = defaultdict(list, things=[6]) # with some dummy data A[3] = defaultdict(list, things=[7]) B = {1: 5, 2: 6, 3: 7, 4: 8, 5: 9} for k, v in B.items(): # print k,v A[k]['things'].append(v) print A print B |
这种回报:
1 2 3 4 5 6 7 8 | defaultdict(<class '__main__.thingdict'>, { 1: defaultdict(<type 'list'>, {'things': [5]}), 2: defaultdict(<type 'list'>, {'things': [6, 6]}), 3: defaultdict(<type 'list'>, {'things': [7, 7]}), 4: {'things': [8]}, 5: {'things': [9]} }) {1: 5, 2: 6, 3: 7, 4: 8, 5: 9} |