# Everything about Counter I think, `collections.Counter` is the most magic and powerful container in Python. This is smart and beautiful [multiset](https://en.wikipedia.org/wiki/Multiset) realization. Let's have a look at what `Counter` can do. ## Basic usage Basic usage for Counter is to count some element (for example, words) in a sequence and get N most popular. ```python from collections import Counter words = 'to be or not to be'.split() c = Counter(words) # Counter({'to': 2, 'be': 2, 'or': 1, 'not': 1}) c.most_common() # [('to', 2), ('be', 2), ('or', 1), ('not', 1)] c.most_common(3) # [('to', 2), ('be', 2), ('or', 1)] ``` Ok, now let's dive into Counter features. ## Init `Counter` is a child of `dict`, and all elements, so you can initialize it from a sequence as in "Basic usage" section or by any way how you initialize `dict`. ```python Counter() Counter('gallahad') Counter({'a': 4, 'b': 2}) Counter(a=4, b=2) Counter({1: 2, 3: 4}) ``` You can use any `int` as value. Yes, zero or negative too. ## Manage values You can get, set and delete values from Counter: ```python c = Counter(first=2, second=3) c['junk'] = 4 c # Counter({'first': 2, 'second': 3, 'junk': 4}) c['junk'] del c['junk'] c # Counter({'first': 2, 'second': 3}) ``` ## Default value If you try to get missing value Counter returns 0 instead of raising `KeyError`: ```python c['missing'] # 0 ``` It allows you to work with `Counter` as with `defaultdict(int)`. Use `in` if you want to check that a Counter contains a key: ```python 'missing' in c # False 'first' in c # True ``` ## Dict Counter has all dict methods: ```python list(c.items()) # [('first', 2), ('second', 3)] list(c.keys()) # ['first', 'second'] list(c.values()) # [2, 3] ``` Method `.update()` smarter than in `dict` and can get anything that you can pass in `init`. Also, it merges values. ```python c = Counter({'first': 1}) c.update(Counter({'second': 2})) c.update({'third': 3}) c.update(fourth=5) c.update(fourth=-1) c.update(['fifth'] * 6) c # Counter({'first': 1, 'second': 2, 'third': 3, 'fourth': 4, 'fifth': 6}) ``` ## Arithmetic operations ```python c1 = Counter(first=1, common=2) c2 = Counter(common=3, second=4) c1 + c2 # Counter({'first': 1, 'common': 5, 'second': 4}) c1 - c2 # Counter({'first': 1}) c2 - c1 # Counter({'common': 1, 'second': 4}) ``` As you can see, arithmetic operations drop negative values. ```python Counter(a=-2) - Counter(a=-1) # Counter() Counter(a=-2) + Counter(a=-1) # Counter() ``` ## Set operations Counter supports set operations: ```python c1 = Counter(first=1, common=2) c2 = Counter(common=3, second=4) c1 & c2 # Counter({'common': 2}) c2 & c1 # Counter({'common': 2}) c1 | c2 # Counter({'first': 1, 'common': 3, 'second': 4}) c2 | c1 # Counter({'common': 3, 'second': 4, 'first': 1}) ``` Union (`|`) This operations also drop non-positive values: ```python Counter(a=-1) | Counter(b=-2) # Counter() ``` ## A little bit more about non-positive values From source code: ```python # Outputs guaranteed to only include positive counts. # To strip negative and zero counts, add-in an empty counter: c += Counter() ``` You can use this magic to drop or flip negative values: ```python +Counter(a=-1) # Counter() +Counter(a=1) # Counter({'a': 1}) -Counter(a=-1) # Counter({'a': 1}) -Counter(a=1) # Counter() ``` ## Get elements Some ways to get elements from Counter: ```python c = Counter(first=1, second=2, third=3) list(c.items()) # [('first', 1), ('second', 2), ('third', 3)] # iterator over elements repeating each as many times as its count list(c.elements()) # ['first', 'second', 'second', 'third', 'third', 'third'] c.most_common() # [('third', 3), ('second', 2), ('first', 1)] c.most_common(2) # [('third', 3), ('second', 2)] ``` ## Conclusion `Counter` is: * Dictionary with a default value, * Supports set and arithmetic operations, * Can count elements in sequence fast because of C realization of this function, * Can return N or all elements sorted by value, * Can merge 2 or more Counters, * Drops negative values. That's beautiful, isn't it?