2009-06-06 146 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语法更易于阅读。