Can I accomplish a rank/sort using Counter.most_common() functionality, thus avoiding this line: d = sorted(d.items(), key=lambda x: (-x[1],x[0]), reverse=False)
??
Challenge: You are given a string.The string contains only lowercase English alphabet characters.Your task is to find the top three most common characters in the string.
Output Format: Print the three most common characters along with their occurrence count each on a separate line. Sort output in descending order of occurrence count. If the occurrence count is the same, sort the characters in ascending order.
In completing this I used dict, Counter, and sort in order to ensure "the occurrence count is the same, sort the characters in ascending order". The in-built Python sorted
functionality ensures ordering by count, then alphabetical. I'm curious if there is a way to override Counter.most_common()
default arbitrary sort/order logic as it seems to disregard the lexicographical order of the results when picking the top 3.
import sys
from collections import Counter
string = sys.stdin.readline().strip()
d = dict(Counter(string).most_common(3))
d = sorted(d.items(), key=lambda x: (-x[1],x[0]), reverse=False)
for letter, count in d[:3]:
print letter, count
Python Counter Counter is an unordered collection where elements are stored as Dict keys and their count as dict value. Counter elements count can be positive, zero or negative integers. However there is no restriction on it's keys and values.
As the source code shows, Counter is just a subclass of dict. Constructing it is O(n), because it has to iterate over the input, but operations on individual elements remain O(1).
The most_common() FunctionThe Counter() function returns a dictionary which is unordered. You can sort it according to the number of counts in each element using most_common() function of the Counter object. You can see that most_common function returns a list, which is sorted based on the count of the elements.
Yes the doc explicitly says Counter.most_common()
's (tie-breaker) order for when counts are equal is arbitrary.
Counter.most_common
with your own sort function like you show, but that's frowned on. (Code you write might accidentally rely on it and hence break when it wasn't patched.)Counter
to MyCounter
so you can override its most_common
. Painful and not really portable.most_common()
most_common()
should not have been hardwired and we should be able to pass a comparison key or sort function into __init__()
.Monkey-patching Counter.most_common()
:
def patched_most_common(self):
return sorted(self.items(), key=lambda x: (-x[1],x[0]))
collections.Counter.most_common = patched_most_common
collections.Counter('ccbaab')
Counter({'a': 2, 'b': 2, 'c': 2})
Demonstrating that in cPython 3.7, the arbitrary order is order of insertion (first insertion of each character):
Counter('abccba').most_common()
[('a', 2), ('b', 2), ('c', 2)]
Counter('ccbaab').most_common()
[('c', 2), ('b', 2), ('a', 2)]
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