2009-06-06 155 views
167

我想創建一個值爲列表的字典。例如:Python創建列表字典

{ 
    1: ['1'], 
    2: ['1','2'], 
    3: ['2'] 
} 

如果我做的:

d = dict() 
a = ['1', '2'] 
for i in a: 
    for j in range(int(i), int(i) + 2): 
     d[j].append(i) 

我得到一個KeyError異常,因爲d [...]是不是列表。在這種情況下,我可以在賦值a之後添加下面的代碼來初始化字典。

for x in range(1, 4): 
    d[x] = list() 

有沒有更好的方法來做到這一點?可以說,我不知道我需要的密鑰,直到我在第二個for循環中。例如:

class relation: 
    scope_list = list() 
... 
d = dict() 
for relation in relation_list: 
    for scope_item in relation.scope_list: 
     d[scope_item].append(relation) 

另一種做法則與

if d.has_key(scope_item): 
    d[scope_item].append(relation) 
else: 
    d[scope_item] = [relation,] 

什麼是處理這個問題的最好辦法更換

d[scope_item].append(relation) 

?理想情況下,追加將「只是工作」。有什麼方法可以表達我想要一個空列表的字典,即使我在第一次創建列表時不知道每個關鍵字?

回答

211

您可以使用defaultdict

>>> from collections import defaultdict 
>>> d = defaultdict(list) 
>>> for i in a: 
... for j in range(int(i), int(i) + 2): 
...  d[j].append(i) 
... 
>>> d 
defaultdict(<type 'list'>, {1: ['1'], 2: ['1', '2'], 3: ['2']}) 
>>> d.items() 
[(1, ['1']), (2, ['1', '2']), (3, ['2'])] 
21

使用setdefault

d = dict() 
a = ['1', '2'] 
for i in a: 
    for j in range(int(i), int(i) + 2): 
     d.setdefault(j, []).append(i) 

print d # prints {1: ['1'], 2: ['1', '2'], 3: ['2']} 

的,而奇怪的命名setdefault功能說「這個鍵獲取值,如果該鍵不存在,添加該值,然後返回。」

編輯:正如其他人正確指出的,defaultdict是一個更好,更現代的選擇。在舊版本的Python中(2.5之前),setdefault仍然有用。

+2

這可以工作,但通常最好在可用時使用defaultdict。 – 2009-06-06 23:25:49

+0

@David,是的,setdefault並不是最精彩的設計,對不起 - 它幾乎不是最好的選擇。我確實認爲我們(Python提交者)用collections.defaultdict兌現了我們的集體聲望,儘管;-)。 – 2009-06-06 23:46:59

37

你可以用列表的理解是這樣構建它:

>>> dict((i, range(int(i), int(i) + 2)) for i in ['1', '2']) 
{'1': [1, 2], '2': [2, 3]} 

而且爲你問題的第二部分使用defaultdict

>>> from collections import defaultdict 
>>> s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)] 
>>> d = defaultdict(list) 
>>> for k, v in s: 
     d[k].append(v) 

>>> d.items() 
[('blue', [2, 4]), ('red', [1]), ('yellow', [1, 3])] 
1

你的問題已經得到解答,但是IIRC你可以取代李網元,如:

if d.has_key(scope_item): 

有:

if scope_item in d: 

也就是說,d引用d.keys()在建設中。有時defaultdict不是最好的選擇(例如,如果要在與上述if關聯的else之後執行多行代碼),並且我發現in語法更易於閱讀。