Python:Collections.Counter vs defaultdict(int)

cov*_*nce 32 python dictionary

假设我有一些如下所示的数据.

Lucy = 1
Bob = 5
Jim = 40
Susan = 6
Lucy = 2
Bob = 30
Harold = 6
Run Code Online (Sandbox Code Playgroud)

我想结合1)删除重复键,2)添加这些重复键的值.这意味着我得到了键/值:

Lucy = 3
Bob = 35
Jim = 40
Susan = 6
Harold = 6
Run Code Online (Sandbox Code Playgroud)

使用(来自集合)计数器或默认字典会更好吗?

Ash*_*ary 44

双方Counterdefaultdict(int)可以工作在这里很好,但它们之间存在一些差异:

  • Counter支持您可以在集中执行的大多数操作.因此,如果您想使用这些操作,请转到计数器.

  • Counter查询丢失的密钥时,不会向dict添加新密钥.因此,如果您的查询包含可能不在dict中的密钥,那么请更好地使用Counter.

例:

>>> c = Counter()
>>> d = defaultdict(int)
>>> c[0], d[1]
(0, 0)
>>> c
Counter()
>>> d
defaultdict(<type 'int'>, {1: 0})
Run Code Online (Sandbox Code Playgroud)

例:

  • Counter还有一个调用方法most_common,允许您按计数对项目进行排序.为了得到同样的东西defaultdict你将不得不使用sorted.

例:

>>> c = Counter('aaaaaaaaabbbbbbbcc')
>>> c.most_common()
[('a', 9), ('b', 7), ('c', 2)]
>>> c.most_common(2)          #return 2 most common items and their counts
[('a', 9), ('b', 7)]
Run Code Online (Sandbox Code Playgroud)
  • Counter 还允许您从Counter对象创建元素列表.

例:

>>> c = Counter({'a':5, 'b':3})
>>> list(c.elements())
['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b']
Run Code Online (Sandbox Code Playgroud)

因此,根据您想要对结果dict做什么,您可以在Counter和之间进行选择defaultdict(int).


ImP*_*0R_ 5

defaultdict(int)似乎工作更快。

\n\n
In [1]: from collections import Counter, defaultdict\n\nIn [2]: def test_counter():\n   ...:     c = Counter()\n   ...:     for i in range(10000):\n   ...:         c[i] += 1\n   ...:\n\nIn [3]: def test_defaultdict():\n   ...:     d = defaultdict(int)\n   ...:     for i in range(10000):\n   ...:         d[i] += 1\n   ...:\n\nIn [4]: %timeit test_counter()\n5.28 ms \xc2\xb1 1.2 ms per loop (mean \xc2\xb1 std. dev. of 7 runs, 100 loops each)\n\nIn [5]: %timeit test_defaultdict()\n2.31 ms \xc2\xb1 68.1 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 100 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n

  • 为什么不将 `range()` 对象直接传递给 `Counter()`? (6认同)
  • @TalJerome 我在 Python 3.6 中测试了这个。 (3认同)
  • 从Python 3.2开始,这可能不成立,请参阅:/sf/ask/1946136181/?lq=1 (2认同)