2011-03-21 65 views
40

我有持有對鍵/值Python列表:列表轉換爲每個鍵具有多個值的字典轉換?

l=[ [1, 'A'], [1, 'B'], [2, 'C'] ] 

我要將列表轉換成一個字典,其中每個鍵多個值將被彙總到一個元組:

{ 1:('A', 'B'), 2:('C',) } 

迭代解決方案很簡單:

l=[ [1, 'A'], [1, 'B'], [2, 'C'] ] 
d={} 
for pair in l: 
    if d.has_key(pair[0]): 
     d[pair[0]]=d[pair[0]]+tuple(pair[1]) 
    else: 
     d[pair[0]]=tuple(pair[1]) 

print d 

{1: ('A', 'B'), 2: ('C',)} 

是否有完成這個任務,更優雅,Python的解決方案嗎?

+1

S/multilpe /多 – vstrien 2011-03-21 13:36:24

+0

'has_key'是的道路上的垃圾箱Python歷史記錄 - 如果您必須測試字典中是否存在密鑰,請使用新的語法「if key in dict:'。但是對於你的問題的「答案」是@ eumiro的defaultdict方法。 – PaulMcG 2011-03-21 13:43:58

+2

@vstrien謝謝。添加一個'/ g'會使它更通用:-) – 2011-03-21 13:51:57

回答

41
from collections import defaultdict 

d1 = defaultdict(list) 

for k, v in l: 
    d1[k].append(v) 

d = dict((k, tuple(v)) for k, v in d1.iteritems()) 

d現在包含{1: ('A', 'B'), 2: ('C',)}

d1是臨時defaultdict使用列表作爲值,這將在最後一行被轉換爲元組。這樣你就可以追加到列表中而不會在主循環中重新創建元組。

+1

+1更好,這是一個新的工具。 – 2011-03-22 12:14:40

7

使用列表,而不是作爲元組字典值:

l=[ [1, 'A'], [1, 'B'], [2, 'C'] ] 
d={} 
for key, val in l: 
    d.setdefault(key, []).append(val) 

print d 
2

的關鍵是已經排序在輸入列表中?如果是這樣的話,你有一個實用的解決方案:

import itertools 

lst = [(1, 'A'), (1, 'B'), (2, 'C')] 
dct = dict((key, tuple(v for (k, v) in pairs)) 
      for (key, pairs) in itertools.groupby(lst, lambda pair: pair[0])) 
print dct 
# {1: ('A', 'B'), 2: ('C',)} 
+0

如果你是'import operator',你可以寫'itertools.groupby(sorted(lst),operator.itemgetter(0))' – eumiro 2011-03-21 14:25:04

+0

@eumiro。是的,我知道。請注意,在這裏使用排序可能會改變所需的輸出,這就是爲什麼我問他們是否已經排序(至少通過鍵)。 – tokland 2011-03-21 14:33:36

10

這種方法比較有效,相當緊湊:

reduce(lambda x, (k,v): x[k].append(v) or x, l, defaultdict(list)) 
+0

不錯,但在python 3.5或更高版本中無效 – Davy 2017-05-15 19:42:35