如何从键/初始计数对列表中初始化计数器?

时间:2017-05-06 20:16:10

标签: python python-3.x data-structures counter python-internals

如果我有一对(key, value)对,我可以快速初始化这样的字典:

>>> data = [ ('a', 1), ('b', 2) ]
>>> dict(data) 
{'a': 1, 'b': 2} 

我想用Counter字典做同样的事情;但怎么样?构造函数和update()方法都将有序对视为键,而不是键值对:

>>> from collections import Counter
>>> Counter(data)
Counter({('a', 1): 1, ('b', 2): 1})

我能做的最好的事情就是使用一个临时的字典,这个字典很丑陋且不必要地迂回:

>>> Counter(dict(data))
Counter({'b': 2, 'a': 1})

是否有正确的方法可以从Counter对列表中直接初始化(key, count)?我的用例涉及从文件中读取大量已保存的计数(使用唯一键)。

3 个答案:

答案 0 :(得分:11)

我只是做一个循环:

for obj, cnt in [ ('a', 1), ('b', 2) ]:
    counter[obj] = cnt

您也可以调用父dict.update方法:

>>> from collections import Counter
>>> data = [ ('a', 1), ('b', 2) ]
>>> c = Counter()
>>> dict.update(c, data)
>>> c
Counter({'b': 2, 'a': 1})

最后,您的原始解决方案没有任何问题:

Counter(dict(list_of_pairs))

创建字典或计数器的昂贵部分是对所有键进行散列并定期调整大小。一旦制作了字典,将其转换为计数器就像dict.copy()一样快便宜。重用哈希值,并且最终的计数器哈希表是预先调整大小的(不需要调整大小)。

答案 1 :(得分:1)

来自docs

  

元素从可迭代计数或从另一个映射(或计数器)

初始化

所以它是,您需要将其转换为映射,然后初始化Counter,当您使用dict进行初始化时,这是正确的举措。

<强>更新

我同意@RaymondHettinger代码看起来不错,实际上它更快

from collections import Counter
from random import choice
from string import ascii_letters
a=[(choice(ascii_letters), i) for i in range(100)]

使用Python 3.6.1和IPython 6进行测试

使用dict进行初始化:

%%timeit
c1=Counter(dict(a))

输出

12.1 µs ± 342 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

使用dict.update()

进行更新
%%timeit    
c2=Counter()
dict.update(c2, a)

输出:

7.21 µs ± 236 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

答案 2 :(得分:0)

如果(key, value)对中的密钥列表已经是唯一的 - 没有重复 - 您可以使用Raymond Hettinger的great solution

请注意,如果有重复的密钥,您只能获得任何给定密钥的最后一个值:

>>> data=[ ('a', 1), ('b', 2), ('a', 3), ('b', 4) ]
>>> c=Counter()
>>> dict.update(c, data)
>>> c
Counter({'b': 4, 'a': 3})      # note 'a' and 'b' are only the last value...

dict相同:

>>> Counter(dict(data))
Counter({'b': 4, 'a': 3})

Counters最常用于计算包含重复项的总数。如果你想要'a'和'b'条目的总和,你需要遍历所有对:

>>> c=Counter()
>>> for k, v in data:
...    c[k]+=v
... 
>>> c
Counter({'b': 6, 'a': 4})        # the sum of the 'k' entries given 'v'