2011-03-31 107 views
19

鑑於n列表中有m字典作爲它們的元素,我想創建一個新的列表並加入一組詞典。每個字典都保證有一個叫做「index」的鍵,但是除此之外可以有一組任意的鍵。非索引鍵不會跨越列表重疊。例如,假設下面的兩個列表:在單個鍵上加入兩個詞典列表

l1 = [{"index":1, "b":2}, {"index":2, "b":3}, {"index":3, "green":"eggs"}] 
l2 = [{"index":1, "c":4}, {"index":2, "c":5}] 

"b"永遠不會出現在l2,因爲它出現在l1,同樣,"c"絕不會出現在l1,因爲它出現在l2

我想製作一個加入列表:

l3 = [{"index":1, "b":2, "c":4}, 
     {"index":2, "b":3, "c":5}, 
     {"index":3, "green":"eggs"}] 

什麼是在Python中這樣做的最有效的方法?

+0

是否保證字典中「索引」條目的值與該字典在列表中的位置相匹配? – 2011-03-31 15:04:21

+0

不 - 不保證「索引」與列表中的字典位置相匹配。 – Bacon 2011-03-31 15:08:50

回答

31
from collections import defaultdict 

l1 = [{"index":1, "b":2}, {"index":2, "b":3}, {"index":3, "green":"eggs"}] 
l2 = [{"index":1, "c":4}, {"index":2, "c":5}] 

d = defaultdict(dict) 
for l in (l1, l2): 
    for elem in l: 
     d[elem['index']].update(elem) 
l3 = d.values() 

# l3 is now: 

[{'b': 2, 'c': 4, 'index': 1}, 
{'b': 3, 'c': 5, 'index': 2}, 
{'green': 'eggs', 'index': 3}] 

編輯:由於l3不保證進行排序(在沒有特定的順序.values()回報的項目),你可以做@ user560833提示:

from operator import itemgetter 

... 

l3 = sorted(d.values(), key=itemgetter("index")) 
+0

即將實施與此非常接近的事情。 – 2011-03-31 15:00:28

+2

之後您需要對l3進行排序 - 不保證列表將按索引順序排列。例如'從運營商導入itemgetter; l3.sort(key = itemgetter(「index」))' – 2011-03-31 16:36:44

+1

取而代之的是對於l in(l1,l2):for elem in l:'最好直接使用'for elem in itertools.chain(l1,l2 )' – klis87 2016-06-07 17:36:47

1

這裏有一襯裏是否這樣:

[dict(sum([z.items() for z in z2],[])) for z2 in [[x3 for x3 in l1+l2 if x3['index']==key] for key in set([x1['index'] for x1 in l1]+[x2['index'] for x2 in l2])]] 

不像列表理解那麼優雅。我不認爲結果必然會按照你想要的方式排序。

擴大一行代碼:

[ 
    dict(sum([z.items() for z in z2],[])) 
    for z2 in [ 
     [ 
      x3 for x3 in l1+l2 if x3['index']==key 
     ] for key in set(
      [x1['index'] for x1 in l1]+[x2['index'] for x2 in l2] 
     ) 
    ] 
] 

六號線的集合表達式得到所有從兩份名單的唯一索引值。圍繞該列表的理解(第3-9行)創建了一個列表,其中每個內部列表都是具有特定索引值的該索引/鍵的字典的組合列表。最外層列表理解爲每個鍵創建一個元組對的單個列表,並將其轉換回字典列表。