1

我有两个清单:

alist =  [11,12,13,11,15]
blist = ['A', 'A', 'B', 'A', 'B']

我想制作一个字典,其中 blist 中的项目是键,alist 中的项目是值,其中列表对应于两个列表中的索引:

结果应该是:

{'A': [11, 12, 11], 'B': [13, 15]}

我试过这个:

dictNames = {}
for i in xrange(len(alist)):
    for letter in blist:
        if letter not in dictNames:
            dictNames[letter] = []
        else:
            dictNames[letter].append(alist[i])

这给出了结果:

{'A': [11, 11, 12, 12, 12, 13, 13, 13, 11, 11, 11, 15, 15, 15], 'B': [11, 12, 12, 13, 13, 11, 11, 15, 15]}

为什么它不附加到字典中预先存在的字母,而不是在它已经在字典中时添加到它?

4

5 回答 5

6

使用 adefaultdict方便:

from collections import defaultdict

dictNames = defaultdict(list)
for key, value in zip(blist, alist):
    dictNames[key].append(value)

这将创建:

>>> dictNames
defaultdict(<type 'list'>, {'A': [11, 12, 11], 'B': [13, 15]})

defaultdict是 的子类,dict因此它仍然可以像其他任何dict.

如果没有defaultdict,您将不得不测试密钥是否已经存在setdefault()

dictNames = {}
for key, value in zip(blist, alist):
    dictNames.setdefault(key, []).append(value)

导致:

>>> dictNames
{'A': [11, 12, 11], 'B': [13, 15]}

这里真正的技巧是使用zip()组合键和值列表而不是双循环。

于 2013-03-21T10:54:58.393 回答
2

首先,您遍历两个列表。对于 alist 中的每一项,它都会遍历 blist。所以内循环运行了 25 次。相反,您希望它运行 5 次,因此您只需要一个循环。

其次,如果列表尚不存在,则正确初始化列表,但在这种情况下,该数字不会添加到列表中。该号码应始终添加到列表中,即使它是一个新列表。

我更改了您的代码以将这两件事考虑在内,并且效果更好:

for i in xrange(len(alist)):
    letter = blist[i]
    if letter not in dictNames:
        dictNames[letter] = []
    dictNames[letter].append(alist[i])

输出:

{'A': [11, 12, 11], 'B': [13, 15]}
于 2013-03-21T11:00:32.760 回答
0

这是我目前能想到的最短的表达方式:

from itertools import groupby

{k: {x[1] for x in v} for k, v in groupby(sorted(zip(blist, alist)), lambda x: x[0])}

相关(尚未提及)部分是对 的调用groupby,也在以下类似问题中进行了描述:Python group by

于 2013-03-21T11:21:44.187 回答
0

这是一个单行解决方案:

 {k: [alist[i] for i in range(len(blist)) if blist[i] == k] for k in set(blist)}

唯一的问题是在最坏的情况下时间复杂度为 O(n^2),不适合大型列表。

于 2013-03-21T11:21:05.513 回答
0

这种方式保持秩序

from collections import defaultdict

alist =  [11,12,13,11,15]
blist = ['A', 'A', 'B', 'A', 'B']

d = defaultdict(list)
seen = defaultdict(set)

for k, v in zip(blist, alist):
    if v not in seen[k]:
        d[k].append(v)
        seen[k].add(v)

print d

defaultdict(<type 'list'>, {'A': [11, 12], 'B': [13, 15]})
于 2013-03-21T11:03:02.487 回答