Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to sort the results of Counter.mostCommon(n) lexicographically (by counter, then by value)?

How can I sort the results of Counter.mostCommon by the counter, and then the value?

My original code:

from collections import Counter
for counter in Counter("abcdefg").most_common(3): 
    print(counter[0], counter[1])

The output is different every time, since each value has a count of 1. Sometimes it is

a 1
b 1
e 1

sometimes

b 1
d 1
f 1

etc.

I want this:

a 1
b 1
c 1

I've also tried sorting the resulting tuples::

from collections import Counter
for counter in sorted(Counter("abcdefg").most_common(3), key=lambda x: x[0]): print(counter[0], counter[1])

and sorting the string

from collections import Counter
for counter in Counter(sorted("abcdefg")).most_common(3): print(counter[0], counter[1])

but I get the same unpredictable results

like image 850
James Wierzba Avatar asked Oct 28 '25 16:10

James Wierzba


1 Answers

The problem here is that Counter dicts are unordered, and most_common doesn't care about the keys. To accomplish this, you need to sort the dict's items and then pull off the 3 most common.

counter = Counter('abcdef')
most_common = sorted(counter.items(), key=lambda pair: (-pair[1], pair[0])) 

This will sort on -pair[1] (the counts) first. Higher counts will appear first because of the negative. Next we sort on pair[0] (the key) which will order lexicographically in normal increasing order.

From here, you need to slice off the items that you want ...

most_common[:3]

Alternatively, we can take a page out of the source code and re-implement most_common to take the keys into account.

import heapq as _heapq

def most_common(counter, n=None):
    '''List the n most common elements and their counts from the most
    common to the least.  If n is None, then list all element counts.

    >>> Counter('abcdeabcdabcaba').most_common(3)
    [('a', 5), ('b', 4), ('c', 3)]

    '''
    # Emulate Bag.sortedByCount from Smalltalk
    sort_key = lambda pair: (-pair[1], pair[0])
    if n is None:
        return sorted(counter.iteritems(), key=sort_key)
    return _heapq.nsmallest(n, counter.iteritems(), key=sort_key)
like image 160
mgilson Avatar answered Oct 30 '25 08:10

mgilson



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!