Reputation: 55
So, I want to sort a dictionary by values and maintain alphabetically in case of ties if the item values are of the same. However, the python dictionary does not save data alphabetically, how to fix it? Thank you in advance!
Here is my code:
from collections import Counter
test = "betty bought a bit of butter but the butter was bitter"
Counter(test.split()).most_common(3)
Output:
[('butter', 2), ('a', 1), ('bitter', 1)]
The desired output should be:
[('butter', 2), ('a', 1), ('betty', 1)]
since that 'bitter' should be behind 'betty' alphabetically.
Upvotes: 1
Views: 956
Reputation: 1123450
Use the heapq.nsmallest()
function with a custom key, passing in a negative count to invert the sort for that part, and the key itself to be returned in alphabetical order:
import heapq
top3 = heapq.nsmallest(
3, Counter(test.split()).items(),
key=lambda kv: (-kv[1], kv[0]))
The Counter.most_common()
method uses heapq.nlargest()
when you give it an argument that is smaller than the number of keys in the dictionary and only uses the counts to determine order, so in case of ties the order is arbitrary. The above is the equivalent for your specific sort order. Just like Counter.most_common()
, this is a O(NlogK) solution (N being the number of items counted, K the number of items you want output).
Demo:
>>> import heapq
>>> from collections import Counter
>>> test = "betty bought a bit of butter but the butter was bitter"
>>> heapq.nsmallest(3, Counter(test.split()).items(), key=lambda kv: (-kv[1], kv[0]))
[('butter', 2), ('a', 1), ('betty', 1)]
Upvotes: 5
Reputation: 142206
Alternatively - you could mix Counter
and OrderedDict
:
from collections import Counter, OrderedDict
class OrderedCounter(Counter, OrderedDict):
pass
test = "betty bought a bit of butter but the butter was bitter"
mc = OrderedCounter(sorted(test.split())).most_common(3)
# [('butter', 2), ('a', 1), ('betty', 1)]
Upvotes: 2