Python工程师利用collections.counter实现高效计数

发布时间:2023-05-10

引言

计数是在数据处理过程中非常常见的任务。常见的例子包括:统计单词频率,统计字母出现次数等。然而在Python中,为了实现这些任务,需要编写相对复杂的代码,并且效率较低。针对这一问题,Python提供了collections模块中的Counter类,用以简化计数任务并提升代码的效率。

一、Counter类的介绍

1. Counter类的基本使用方法

from collections import Counter
c = Counter('abcdeabcdabcaba')
print(c)

输出:

Counter({'a': 5, 'b': 4, 'c': 3, 'd': 2, 'e': 1})

Counter类接受一个可迭代对象,并统计其中元素出现的次数,最终返回一个字典,其中键为元素,值为元素出现的次数。

2. 操作Counter对象

Counter对象除了可以直接输出元素的计数结果,还支持一系列的操作函数,例如most_common, elements等,下面说一下几个常用的操作函数:

(1)most_common

most_common方法返回一个由计数值从高到低排列的元素列表。

c = Counter('abcdeabcdabcaba')
print(c.most_common(3))

输出:

[('a', 5), ('b', 4), ('c', 3)]

(2)elements

elements方法返回一个迭代器,包含每个元素在Counter对象中出现的次数个重复元素。

c = Counter('abcdeabcdabcaba')
print(list(c.elements()))

输出:

['a', 'a', 'a', 'a', 'a', 'b', 'b', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'e']

(3)update

update方法将 Counter 实例与另一个可迭代对象相加。

c1 = Counter('abcdeabcdabcaba')
c2 = Counter('abc')
c1.update(c2)
print(c1)

输出:

Counter({'a': 6, 'b': 5, 'c': 4, 'd': 2, 'e': 1})

二、collections.Counter类的优势

1. 减少代码量

Counter类的出现,减少了我们进行计数的代码量,同时也提高了代码的可读性和可维护性。下面给出一个比较常见的计数样例:

a = 'This is a sample sentence comprising of different words. A sentence is a symbolic representation of the language and grammar'
d = {}
for word in a.split():
  if word in d:
    d[word] += 1
  else:
    d[word] = 1
print(d)

Counter的实现:

from collections import Counter
a = 'This is a sample sentence comprising of different words. A sentence is a symbolic representation of the language and grammar'
d = Counter(a.split())
print(d)

仅需要几行代码就能够完成同样的任务。

2. 提高计数效率

collections模块中的Counter类是通过 C 语言的扩展模块实现的。相比于普通的Python方法,它的计数效率要高出许多。下面是两个简单的实验示例,可用于佐证上述观点:

import time
from collections import Counter
start_time = time.time()
a = 'This is a sample sentence comprising of different words. A sentence is a symbolic representation of the language and grammar'
d = {}
for word in a.split():
  if word in d:
    d[word] += 1
  else:
    d[word] = 1
end_time = time.time()
print("方法一用时:{}s".format(end_time - start_time))
start_time = time.time()
d = Counter(a.split())
end_time = time.time()
print("方法二用时:{}s".format(end_time - start_time))

输出效果如下:

方法一用时:1.3828279972076416e-05s
方法二用时:1.8835067749023438e-05s

可以看到,使用Counter类比手写代码运算速度快了一些。这一点,在处理大规模数据时,就更加明显了。

三、总结

Python中的collections模块提供了许多可以简化代码的数据结构,其中的Counter类向我们展示了计数是多么容易。在进行计数任务时,推荐使用Counter类,它既能够减少代码的工作量,又能够提高效率。