Counter
实现:
1 | class collections.Counter([iterable-or-mapping]) |
源码中,简单介绍了一些用法:
1 | 'abcdeabcdabcaba') # count elements from a string c = Counter( |
Counter
是dict的子类,可以用来计算可哈希对象的数量。它是一个无序的集合,并且元素作为dict的key,数量作为dict的value。数量可以是任意整数值,包括0和负数。
1 | # a new, empty counter c = Counter() |
对于那些不存在的元素,如果想要获取它,Counter会返回0,而不会引发KeyError
:
1 | 'eggs', 'ham']) c = Counter([ |
从源码中可以看出来为什么不引发KeyError
:
1 | def __missing__(self, key): |
如果count设置为零或减少为零,它将保留在counter中,直到删除该条目或清除计数器:
1 | 'sausage'] = 0 # counter entry with a zero count c[ |
由于Counter是dict的子类,因此他具备dict的方法。除此之外,它还具备以下方法:
elements()
返回每一个元素,元素会根据个数重复count次,并且是以任意顺序返回的。如果元素的个数小于1(包括负值),那么就会被忽略不返回
1
2
3>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> sorted(c.elements())
['a', 'a', 'a', 'a', 'b', 'b']most_common([n])
返回n个最常见元素及其计数的列表,从最常见到最少。 如果省略n或None,则most_common()返回计数器中的所有元素。 具有相同计数的元素是任意排序的:
1
2>>> Counter('abracadabra').most_common(3)
[('a', 5), ('r', 2), ('b', 2)]subtract([iterable-or-mapping])
根据迭代器或映射中对当前元素进行加减操作。和
dict.update()
类似,但是注意,是操作,而不是替换。输入和输出可以为0或负数1
2
3
4
5>>> c = Counter(a=4, b=2, c=0, d=-2)
>>> d = Counter(a=1, b=2, c=3, d=4)
>>> c.subtract(d)
>>> c
Counter({'a': 3, 'b': 0, 'c': -3, 'd': -6}
通常情况下,Counter对象和字典具有相同的方法。但是以下两个方法会有所不同:
fromkeys(iterable)
Counter类没有实现这个方法
update([iterable-or-mapping])
和
dict.update()
相似,但是是进行加减操作,而不是替换。从源码看,更容易理解一些:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39def update(*args, **kwds):
'''Like dict.update() but add counts instead of replacing them.
Source can be an iterable, a dictionary, or another Counter instance.
>>> c = Counter('which')
>>> c.update('witch') # add elements from another iterable
>>> d = Counter('watch')
>>> c.update(d) # add elements from another counter
>>> c['h'] # four 'h' in which, witch, and watch
4
'''
# The regular dict.update() operation makes no sense here because the
# replace behavior results in the some of original untouched counts
# being mixed-in with all of the other counts for a mismash that
# doesn't have a straight-forward interpretation in most counting
# contexts. Instead, we implement straight-addition. Both the inputs
# and outputs are allowed to contain zero and negative counts.
if not args:
raise TypeError("descriptor 'update' of 'Counter' object "
"needs an argument")
self, *args = args
if len(args) > 1:
raise TypeError('expected at most 1 arguments, got %d' % len(args))
iterable = args[0] if args else None
if iterable is not None:
if isinstance(iterable, _collections_abc.Mapping):
if self:
self_get = self.get
for elem, count in iterable.items():
self[elem] = count + self_get(elem, 0)
else:
super(Counter, self).update(iterable) # fast path when counter is empty
else:
_count_elements(self, iterable)
if kwds:
self.update(kwds)
官网给出一些常见操作:
1 | sum(c.values()) # total of all counts |
提供了几个数学运算来组合Counter对象以生成多个集合(计数大于零的计数器)。 加法和减法通过添加或减去相应元素的计数来组合计数器。 &和 | 返回相应计数的最小值和最大值。 每个操作都可以接受带有符号计数的输入,但输出将排除计数为零或更少的结果。
1 | 3, b=1) c = Counter(a= |
一元加法和减法是用于添加空计数器或从空计数器中减去的快捷方式。
1 | 2, b=-4) c = Counter(a= |
注意 : Counter主要用于处理正整数的计数。但是也不要忘记考虑其他类型或负值的情况。Counter类继承自dict,对于key和value是没有限制的。value除了数字也可以存储其他。