2016-07-28 47 views
0

給定n個包含m個詞典作爲其元素的列表,我想用一個連接的詞典集產生一個新列表。根據鍵值對匹配添加兩個詞典列表中的元素匹配

l1 = [{"index":'a', "b":2,'c':9}, {"index":'b', "b":3,"c":5}, {"index":'c', "b":8,"c":8}] 
l2 = [{"index":'a', "b":4,'c':8}, {"index":'b', "b":9,"c":10},{"index":None, "b":11,"c":10}] 

我想產生一個加入列表:

l3 = [{"index":'a', "b":6, "c":17}, 
    {"index":'b', "b":12, "c":15}, 
    {"index":'c', "b":8, "c":8}, 
    {"index":None, "b":11,"c":10}] 

我有可以合併兩個列表的方法。但正如你在上面看到的,我也想添加這些元素。

def merge_lists(l1, l2, key): 
merged = {} 
for item in l1+l2: 
    if item[key] in merged: 
    merged[item[key]].update(item) 
    else: 
    merged[item[key]] = item 
return [val for (_, val) in merged.items()] 

l3 = merge_lists(l1,l2,'index') 

什麼是在Python中執行此操作的最有效方法?

+0

具有相同的「索引」的字典總是在列表中的相同位置?如果不是,他們是否應該合併? –

回答

4

可以使用Counter這樣的事情很容易...

from collections import defaultdict, Counter 

def merge_lists(l1, l2): 
    d = defaultdict(Counter) 
    for sdict in l1 + l2: 
     counter = Counter(sdict) 
     d[counter.pop('index')] += counter  

    lists = [] 
    for k, v in d.items(): 
     result = dict(v) 
     result['index'] = k 
     lists.append(result) 
    return lists 

l1 = [{"index":'a', "b":2,'c':9}, {"index":'b', "b":3,"c":5}, {"index":'c', "b":8,"c":8}] 
l2 = [{"index":'a', "b":4,'c':8}, {"index":'b', "b":9,"c":10},{"index":None, "b":11,"c":10}] 
print(merge_lists(l1, l2)) 

有關添加Counter情況下的偉大的事情是,它非常簡單,只是做你的期望。如果一個計數器沒有密鑰,它就不會對和數增加任何內容,但是如果兩個計數器都有給定的密鑰,那麼它們的值將被添加並用作該密鑰的結果值。


注意,合併後的列表的順序是任意的(基於defaultdict的順序)。如果您需要以某種方式維持秩序,您可以sort事後或創建一個默認的排序字典將保留根據訂單時indexl1l2是第一次看到:

class DefaultOrderedDict(collections.OrderedDict): 

    def __init__(self, default_factory, *args, **kwargs): 
     self.default_factory = default_factory 
     super(DefaultOrderedDict, self).__init__(*args, **kwargs) 

    def __missing__(self, key): 
     self[key] = self.default_factory() 
     return self[key] 

(有是更「完整」的默認有序字典浮動在ActiveState和StackOverflow周圍,但這個簡單的應該你的問題手頭上工作)