[英]python quickest way to merge dictionaries based on key match
我有2個詞典列表。 列表A長34,000,列表B長650,000。 我基本上是根據鍵匹配將所有List B dicts插入到List A dicts中。 目前,我做的很明顯,但它永遠服用(嚴肅地說,就像一天)。 必須有一個更快的方式!
for a in listA:
a['things'] = []
for b in listB:
if a['ID'] == b['ID']:
a['things'].append(b)
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)
基本上它通過'預先計算'從listB匹配每個'ID'的dicts來避免循環遍歷listB中每個dict的listB中的每個dict
這是一種可能有所幫助的方法。 我會留給你填寫細節。
你的代碼很慢,因為它是一個O(n ^ 2)算法,將每個A與每個B進行比較。
如果您首先按id(這些是O(nlogn))操作對listA和listB中的每一個進行排序,那么您可以輕松地遍歷A和B的排序版本(這將是線性時間)。
當您必須在非常大的數據集上進行外部合並時,這種方法很常見。 Mihai的答案更適合內部合並,你只需按id(在內存中)索引所有內容。 如果你有內存來保存這些額外的結構,並且字典查找是恆定的時間,那么這種方法可能會更快,更不用說更簡單了。 :)
舉個例子,假設A 在排序后有以下ID
acfgjp
排序后,B又有了這些ID
aaaabbbbcccddeeeefffggiikknnnnppppqqqrrr
奇怪的是,這個想法是將索引保持在A和B中(我知道這聽起來不像Pythonic)。 起初,你正在尋找a
A和a
在B.所以,你到B將所有的一對你的“東西”陣列走a
。 一旦你在B中消耗了a,你就會在A中向上移動一個到c
。 但是B中的下一個項目是b
,它小於c
,所以你必須跳過b。 然后你到達B中的c
,所以你可以開始為c添加“東西”。 以這種方式繼續,直到兩個列表都用盡。 只需一次通過。 :)
我將ListA和ListB轉換為字典,而不是以ID為鍵的字典。 然后使用python的快速字典查找附加數據是一件簡單的事情:
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
返回:
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}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.