Reputation: 24811
I was reading python collections's Counter. It says following:
>>> from collections import Counter
>>> Counter({'z': 9,'a':4, 'c':2, 'b':8, 'y':2, 'v':2})
Counter({'z': 9, 'b': 8, 'a': 4, 'c': 2, 'y': 2, 'v': 2})
Somehow these printed values are printed in descending order (9 > 8 > 4 > 2). Why is it so? Does Counter
store values sorted?
PS: Am on python 3.7.7
Upvotes: 3
Views: 1291
Reputation: 262204
The order depends on the python version.
For python < 3.7, there is no guaranteed order, since python 3.7 the order is that of insertion.
Changed in version 3.7: As a dict subclass, Counter inherited the capability to remember insertion order. Math operations on Counter objects also preserve order. Results are ordered according to when an element is first encountered in the left operand and then by the order encountered in the right operand.
Example on python 3.8 (3.8.10 [GCC 9.4.0]):
from collections import Counter
Counter({'z': 9,'a':4, 'c':2, 'b':8, 'y':2, 'v':2})
Output:
Counter({'z': 9, 'a': 4, 'c': 2, 'b': 8, 'y': 2, 'v': 2})
Counter
doesn't sort by countAs __str__
in Counter
return the most_common
, it is not a reliable way to check the order.
Convert to dict
, the __str__
representation will be faithful.
c = Counter({'z': 9,'a':4, 'c':2, 'b':8, 'y':2, 'v':2})
print(dict(c))
# {'z': 9, 'a': 4, 'c': 2, 'b': 8, 'y': 2, 'v': 2}
Upvotes: 3
Reputation: 13599
In terms of the data stored in a Counter
object: The data is insertion-ordered as of Python 3.7, because Counter
is a subclass of the built-in dict
. Prior to Python 3.7, there was no guaranteed order of the data.
However, the behavior you are seeing is coming from Counter.__repr__
. We can see from the source code that it will first try to display using the Counter.most_common
method, which sorts by value in descending order. If that fails because the values are not sortable, it will fall back to the dict
representation, which, again, is insertion-ordered.
Upvotes: 9