Does Counter from collections maintain order after frequency has been considered?
e.g.
s= "leetcode"
cnt = Counter(s)
for el in s:
if cnt[el] == 1:
return el
So for the above code, the output looks something like:
Counter({'e': 3, 'l': 1, 't': 1, 'c': 1, 'o': 1, 'd': 1})
Now, I know Counter presents key/value in descending order, hence 'e' appears first as it has the highest count of 3, but after this all other elements have a counter of 1- does this mean that the Counter will always maintain the order of the string/array? It clearly does for the above example, but I wanted to make sure it isn't just my IDE that does this (Pycharm)
A Counter
is really just a dict
with some extra functionality. The underlying dictionary retains insertion order in recent versions of Python, as is called out in the docs:
Changed in version 3.7: As a
dict
subclass,Counter
Inherited the capability to remember insertion order.
You can see this if you e.g. print the keys, which keep the order they were seen in the source string:
>>> print(cnt.keys())
dict_keys(['l', 'e', 't', 'c', 'o', 'd'])
However, note that the __repr__
has specific handling for order:
def __repr__(self):
if not self:
return f'{self.__class__.__name__}()'
try:
# dict() preserves the ordering returned by most_common()
d = dict(self.most_common())
except TypeError:
# handle case where values are not orderable
d = dict(self)
return f'{self.__class__.__name__}({d!r})'
The Counter
is displayed in most_common
order, whose current documentation says:
Elements with equal counts are ordered in the order first encountered
The implementation uses sorted
, which is:
...guaranteed to be stable. A sort is stable if it guarantees not to change the relative order of elements that compare equal...
hence retaining the insertion order of elements with equal counts.
Earlier versions of the most_common
docs, though, say:
Elements with equal counts are ordered arbitrarily
because the dictionary was arbitrarily ordered to begin with.