collection.Counter(对象计数)

collection.Counter类: 一个方便统计对象数量的类,提供了一些方便使用的方法。它是内置dict类的子类,所以也具有dict的绝大部分特性及功能。

我们统计一个列表,元组,等序列时,有时需要统计每种元素出现的次数。 下面示例模拟一个我们自己会实现的方法:

word = "mississippi"
counter = {}

for letter in word:
    if letter not in counter:
        counter[letter] = 0
    counter[letter] += 1

print(counter)   # {'m': 1, 'i': 4, 's': 4, 'p': 2}

我们把每种元素做为key,将其出现的次数做为value,放在一个数据字典中。

现在我们使用Counter类来实现上面的统计功能。

from collections import Counter

word = "mississippi"
# Use a string as an argument
print(Counter("mississippi"))
# Use a list as an argument
print(Counter(list("mississippi")))

Counter类通过传入可迭代对象,就构造了一个Counter对象,同时内部统计数据会存储为数据字典结构。
Counter对象的构造: 不传参数则实例化一个空的Counter对象。除此之外,可以传入iterable, dictionary, 命名参数等。甚至可以将另一个counter对象做为参数。

c = Counter()                           # a new, empty counter
c = Counter('gallahad')                 # a new counter from an iterable
c = Counter({'red': 4, 'blue': 2})      # a new counter from a mapping
c = Counter(cats=4, dogs=8)             # a new counter from keyword args

可以用c['key']的方式来访问一个数据,但与dict不同的是,如果该'key'不存在不会报错,而是返回0。 而c['key'] = 0 不是删除'key',而是应该使用del c['key']来删除。

from collections import Counter

c = Counter(['eggs', 'ham'])
print(c)   # Counter({'eggs': 1, 'ham': 1})
print('-' * 25, '分隔线', '-' * 25)

print(c['bacon'])  # 0
c['eggs'] = 0
print(c)    # Counter({'ham': 1, 'eggs': 0})

print('-' * 25, '分隔线', '-' * 25)
del c['eggs']
print(c)  # Counter({'ham': 1})

Counter.elements(): 返回一个迭代器,元素的顺序与Counter中的key的顺序保持一致。

from collections import Counter

c = Counter(a=4, b=2, c=0, d=-2)
print(list(c.elements()))  # ['a', 'a', 'a', 'a', 'b', 'b']

Counter.most_common([n]): 返回一个(key, count)元组的列表,按照出现元素出现次数的高低顺序来返回。如果指定了参数n,则只返回前n项。 当两个key对应相同的count时,由原始iterable中元素出现的先后顺序决定。

from collections import Counter

print(Counter('abracadabra').most_common(3))  # [('a', 5), ('b', 2), ('r', 2)]

如果我们想返回计数最低的三个元素,可以通过切片方式获得c.most_common()[:-n-1:-1]Counter('abracadabra').most_common(3)[:-4:-1]

Counter.subtract([iterable-or-mapping]): 从当前统计对象中减掉另一个统计对象中对应的key, count值。可传参数为iterable,或者mapping(即dict或Counter对象)

from collections import Counter

c = Counter(a=4, b=2, c=0, d=-2 ,e=7)
d = Counter(a=1, b=2, c=3, d=4 , f=8)
c.subtract(d)
print(c)  # Counter({'e': 7, 'a': 3, 'b': 0, 'c': -3, 'd': -6, 'f': -8})

Counter.update([iterable-or-mapping]): 从当前统计对象中加上另一个统计对象中对应的key, count值。可传参数为iterable,或者mapping(即dict或Counter对象)。其作用正好与subtract方法相反。

from collections import Counter

c = Counter(a=4, b=2, c=0, d=-2 ,e=7)
d = Counter(a=1, b=2, c=3, d=4 , f=8)
c.update(d)
print(c)  # Counter({'f': 8, 'e': 7, 'a': 5, 'b': 4, 'c': 3, 'd': 2})

Counter.total(): 将各个key的统计数量相加。

from collections import Counter

c = Counter(a=10, b=5, c=0)
print(c.total())  # 15 

counter对象支持的运算符
比较运算符: ==, !=, <, <=, >, >=, 比较时会忽略0计数的项。比如Counter(a=1) == Counter(a=1, b=0)返回True
数学运算符+,-,&,|, 加,减,交集,并集。
加减运算与update和substract函数略有不同。计算后计数<=0的项会被移除。

from collections import Counter

c = Counter(a=10, b=5, c=0,d=-2)
d = Counter(a=10, b=5, e=7)
print(c + d)  # Counter({'a': 20, 'b': 10, 'e': 7})
print(c - d)  # Counter() 空的

交集与并集计算的结果也会移除计数<=0的项。

from collections import Counter

c = Counter(a=8, b=5, c=0,d=-2)
d = Counter(a=10, b=3, e=7)

print(c & d)  # Counter({'a': 8, 'b': 3})
print(c | d)  # Counter({'a': 10, 'e': 7, 'b': 5})

单目运算符+c相当于移除计数<=0的项。 -c相当于将所有计数取相反数,然后再移除计数<=0的项。

from collections import Counter

c = Counter(a=8, b=5, c=0,d=-2)

print(+c)  # Counter({'a': 8, 'b': 5})
print(-c)  # Counter({'d': 2})
posted @ 2025-01-20 12:25  RolandHe  阅读(113)  评论(0)    收藏  举报