If I have a sequence of (key, value)
pairs, I can quickly initialize a dictionary like this:
>>> data = [ ('a', 1), ('b', 2) ]
>>> dict(data)
{'a': 1, 'b': 2}
I would like to do the same with a Counter
dictionary; but how? Both the constructor and the update()
method treat the ordered pairs as keys, not key-value pairs:
>>> from collections import Counter
>>> Counter(data)
Counter({('a', 1): 1, ('b', 2): 1})
The best I could manage was to use a temporary dictionary, which is ugly and needlessly circuitous:
>>> Counter(dict(data))
Counter({'b': 2, 'a': 1})
Is there a proper way to directly initialize a Counter
from a list of (key, count)
pairs? My use case involves reading lots of saved counts from files (with unique keys).
Initializing. Counter supports three forms of initialization. Its constructor can be called with a sequence of items, a dictionary containing keys and counts, or using keyword arguments mapping string names to counts. To create an empty counter, pass the counter with no argument and populate it via the update method.
In Python, you can count the total number of elements in a list or tuple with the built-in function len() and the number of occurrences of an element with the count() method.
Counter is a subclass of dict that's specially designed for counting hashable objects in Python. It's a dictionary that stores objects as keys and counts as values. To count with Counter , you typically provide a sequence or iterable of hashable objects as an argument to the class's constructor.
A Counter is a dict subclass for counting hashable objects. It is a collection where elements are stored as dictionary keys and their counts are stored as dictionary values. Counts are allowed to be any integer value including zero or negative counts.
I would just do a loop:
for obj, cnt in [ ('a', 1), ('b', 2) ]:
counter[obj] = cnt
You could also just call the parent dict.update
method:
>>> from collections import Counter
>>> data = [ ('a', 1), ('b', 2) ]
>>> c = Counter()
>>> dict.update(c, data)
>>> c
Counter({'b': 2, 'a': 1})
Lastly, there isn't anything wrong with your original solution:
Counter(dict(list_of_pairs))
The expensive part of creating dictionaries or counters is hashing all of the keys and doing periodic resizes. Once the dictionary is made, converting it to a Counter is very cheap about as fast as a dict.copy(). The hash values are reused and the final Counter hash table is pre-sized (no need for resizing).
From docs:
Elements are counted from an iterable or initialized from another mapping (or counter)
So it's a No, you need to convert it to mapping and then initialize Counter
. And Yes when you initialized with dict
it was the right move.
UPDATE
I agree that @RaymondHettinger code looks good, and actually it's faster
from collections import Counter
from random import choice
from string import ascii_letters
a=[(choice(ascii_letters), i) for i in range(100)]
Tested with Python 3.6.1 and IPython 6
Initialization with dict
:
%%timeit
c1=Counter(dict(a))
Output
12.1 µs ± 342 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
Update with dict.update()
%%timeit
c2=Counter()
dict.update(c2, a)
Output:
7.21 µs ± 236 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With