Python 标准库中的 collections.Counter
类实现了多重集合, 该类型允许在集合中多次出现同一个元素
Python 类型
多重集合 Counter 实质上是一个字典, 键表示具体元素, 值表示该元素出现的次数, 即该元素在整个集合中的数量
>>> from collections import Counter
>>> issubclass(Counter, dict)
True
与字典不同的是, 当键不存在时, Counter 不会报错
>>> c = Counter()
>>> c['x']
0
键不存在时, 元素的个数自然为 0
新建
Counter([iterable-or-mapping])
除了可以从可迭代对象获取初始元素外, 还能以字典的方式创建 Counter (键值对中的值为元素个数)
# 可迭代对象
>>> c_1 = Counter("xy")
>>> c_1
Counter({
'x': 1, 'y': 1})
# 以下均为以字典的方式创建 Counter
# 'x' 和 'y' 均有 2 个
>>> c_2 = Counter({
'x': 2, 'y': 2})
>>> c_2
Counter({
'x': 2, 'y': 2})
>>> c_3 = Counter(x=3, y=3)
>>> c_3
Counter({
'x': 3, 'y': 3})
# 2-tuple
>>> c_4 = Counter([('x', 4), ('y', 4)])
>>> c_4
Counter({
('x', 4): 1, ('y', 4): 1})
操作
- 加减运算
+
和 -
的运算规则:
- 对元素的计数进行加减
- 仅保留计数为正的元素
运算结果返回新的 Counter 对象
# 'x' 和 'y' 的计数都 +2
>>> c_1 + c_2
Counter({
'x': 3, 'y': 3})
# 'x' 和 'y' 的计数不变, 'z' 的计数 +1
>>> c_1 + Counter('z')
Counter({
'x': 1, 'y': 1, 'z': 1})
# 'z' 的计数为 -1(舍弃)
>>> c_1 - Counter('z')
Counter({
'x': 1, 'y': 1})
# 'x' 和 'y' 的计数均为 -1(均舍弃)
>>> c_1 - c_2
Counter()
除了 +
与 -
运算, Counter 还提供了加减运算的实例方法
- 减法
c.subtract([iterable-or-mapping])
- 加法
c.update([iterable-or-mapping])
与运算符的加减不同, subtract
和 update
均保留计数小于等于 0 的元素, 并且会修改 c 本身
>>> c_1.subtract(c_2)
>>> c_1
Counter({
'x': -1, 'y': -1})
# 'x' 个数 +2
>>> c_1.update('xx')
>>> c_1
Counter({
'x': 1, 'y': -1})
- 集合运算
作为多重集合, 自然支持集合运算
- 交集
选取两个 Counter 都有的元素, 元素的个数取较小值
- 并集
选取两个 Counter 的所有元素, 元素的个数取较大值
# 没有共同元素
>>> Counter('xy') & Counter('z')
Counter()
# 共同元素 'x', 个数取较小值 1
>>> Counter('xxy') & Counter('xz')
Counter({
'x': 1})
# 新集合包含 'x' 'y' 'z' 3 个元素
>>> Counter('xy') | Counter('z')
Counter({
'x': 1, 'y': 1, 'z': 1})
>>> Counter('xxy') | Counter('xz')
Counter({
'x': 2, 'y': 1, 'z': 1})
- 其他方法
c.elements()
所有元素的可迭代对象(包含重复)c.most_common([n])
个数最多的前 n 个元素及其数量c.clear
清空
>>> c = Counter('abbcccdddd')
>>> c
Counter({
'd': 4, 'c': 3, 'b': 2, 'a': 1})
>>> c.elements()
<itertools.chain object at 0x7ff1352bd400>
>>> list(c.elements())
['a', 'b', 'b', 'c', 'c', 'c', 'd', 'd', 'd', 'd']
>>> c.most_common(2)
[('d', 4), ('c', 3)]
注意: len(c)
表示不重复元素的个数, 真正的元素个数为 sum(c.values())
或者 c.total()
(Python 3.10 才支持)
>>> c
Counter({
'd': 4, 'c': 3, 'b': 2, 'a': 1})
>>> len(c)
4
>>> sum(c.values())
10