如果我有一对(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)
?我的用例涉及从文件中读取大量已保存的计数(使用唯一键)。
答案 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'