使用Counter对象从两个列表创建字典

时间:2014-12-05 10:24:25

标签: python list dictionary counter idiomatic

我有以下列表:

name = ["Anne", "Jack", "Mary"]

我还有一个嵌套列表,其中每个元素都是另一个列表,并与name列表索引中的名称相关联。如下所示:

n1 = [[0, 0, 3], [0, 5, 5], [1, 3, 3]]

因此'Anne'是列表name中的第一个元素,与n1相关联的列表是第一个元素[0, 0, 3]

同样,对于"Jack",列表name中的第二个元素,与n1相关联的列表是第二个元素[0, 5, 5],依此类推。

我想计算n1每个元素中每个数字的出现次数,并以字典格式将其连接到name列表中的名称。

所以我希望我的输出看起来如下所示:

{'Anne': {'0': 2, '3': 1}, 'Jack': {'0': 1, '5': 2}, 'Mary': {'1': 1, '3': 2}}

我试过以下内容:

      from collections import Counter
      clust = {}
      for val in name:
         clust[val] = {}
         for e in n1:
             wc = Counter(str(e1) for e1 in e)
             clust[val] = dict(wc)

但这给了我输出:

clust = {'Anne': {'1': 1, '3': 2}, 'Jack': {'1': 1, '3': 2}, 'Mary': {'1': 1, '3': 2}}

哪个不对。如何实现我想要的输出?

5 个答案:

答案 0 :(得分:4)

您需要将n1中的数据与name中的每个项目进行匹配;最简单的方法是zip

>>> from collections import Counter
>>> name = ["Anne", "Jack", "Mary"]
>>> n1 = [[0,0,3], [0,5,5], [1,3,3]]
>>> {name_: Counter(data) for name_, data in zip(name, n1)}
{'Anne': Counter({0: 2, 3: 1}), 'Jack': Counter({5: 2, 0: 1}), 'Mary': Counter({3: 2, 1: 1})}

(请注意使用"词典理解",请参阅the docs。)

如果Counter s字符串中的键是至关重要的,则可以在计数之前使用map转换整数:

>>> {name_: Counter(map(str, data)) for name_, data in zip(name, n1)}
{'Anne': Counter({'0': 2, '3': 1}), 'Jack': Counter({'5': 2, '0': 1}), 'Mary': Counter({'3': 2, '1': 1})}

答案 1 :(得分:2)

对于每个名称,您的for e in n1:循环遍历n1的所有元素,为每个元素创建一个计数器,并将clust[val]设置为结果。因此,clust[val]仅作为n1中最后一项的结果而结束。

您应该使用zip()将两个列表名称和n1组合成一个或更好的名称列表和来自n1的结果计数器。 zip()返回带有从两个列表中取得的元素的元组(zip([1, 2], ['a', 'b']) becomes [(1, 'a'), (2, 'b')]。您可以直接从这些元组中创建dict

所以:

clust = dict(zip(name, [Counter(e) for e in n1]))

答案 2 :(得分:1)

只需使用name列表的索引值来计算n1子列表中的项目。这可以使用enumerate(name)完成。它返回值及其索引。使用此返回的索引计算与n1中的项目对应的name子列表中的项目。

>>> from collections import Counter
>>> name = ["Anne", "Jack", "Mary"]
>>> n1 = [[0,0,3], [0,5,5], [1,3,3]]
>>> clust = {}
>>> for i,val in enumerate(name):
...     wc = Counter(str(e1) for e1 in n1[i])
...     clust[val] = dict(wc)
... 
>>> clust
{'Anne': {'0': 2, '3': 1}, 'Jack': {'0': 1, '5': 2}, 'Mary': {'1': 1, '3': 2}}

答案 3 :(得分:0)

你需要像这样得到这个

from collections import Counter
name = ["Anne", "Jack", "Mary"]
n1 = [[0,0,3], [0,5,5], [1,3,3]]
clust = {name[i]: Counter(n1[i]) for i in range(len(name))}

输出是:

{'Anne': Counter({0: 2, 3: 1}), 'Jack': Counter({5: 2, 0: 1}), 'Mary': Counter({3: 2, 1: 1})}

答案 4 :(得分:0)

这是一个获得所需输出的衬垫:

zip(name, [dict(Counter(z)) for z in [[str(y) for y in x] for x in n1]])

要打破它:

  • [[str(y) for y in x] for x in n1]将n1个元素转换为列表
  • dict(Counter(z))创建一个列表,计算每个n1列表的元素
  • zip结合了两个列表