12

I have a Counter that is already ordered by number of occurrences.

counterlist = Counter({'they': 203, 'would': 138, 'your': 134,...}).

But when I do counterlist.keys() the return list is:

['wirespe', 'four', 'accus',...]

instead of

['they', 'would', 'your',...].

Why?

Mazdak
  • 105,000
  • 18
  • 159
  • 188
user3005486
  • 179
  • 1
  • 3
  • 9
  • If `keys` is giving you keys which are not in your `Counter`... you called it on the wrong dictionary. – timgeb Jan 28 '16 at 20:45
  • 1
    python dictionaries are NOT ordered. `{...}` is a dictionary. – Aprillion Jan 28 '16 at 20:46
  • I have the impression the OP, by chance, got an ordered printout, but then calling `.keys()` on it the result differs. Unfortunately, the examples, as pointed out above, do not share a single key, so it's impossible to tell – Pynchia Jan 28 '16 at 20:47
  • Do you mean you want the keys in order of their count? Use `counterlist.most_common()` for that (or `[e[0] for e in counterlist.most_common()]`. – mata Jan 28 '16 at 20:54

4 Answers4

19

Counter()

A Counter is a dict subclass for counting hashable objects. It is an unordered collection where elements are stored as dictionary keys and their counts are stored as dictionary values.

is an unordered dict so it does not keep the order in which you added them to the dict. If you want to keep them in order you will need to use an OrderedDict()

If you want an OrderedCounter() then you could do this which I am pulling from here which has an explanation as to why it works.

from collections import *

class OrderedCounter(Counter, OrderedDict):
    pass

counterlist = OrderedCounter({'would': 203, 'they': 138, 'your': 134})

print counterlist.keys()
SirParselot
  • 2,640
  • 2
  • 20
  • 31
  • 1
    This is old as Python has dict order by default. – Phil May 25 '20 at 19:38
  • 2
    Python 3.6 and up has dict order. Here's a great response detailing it. https://stackoverflow.com/a/39980744/5012922 – SirParselot May 27 '20 at 22:07
  • This also doesn't really solve the OP's problem, as it only guarantees the order in which things were inserted, so doesn't return them in order of size – tdc Sep 24 '20 at 22:43
5

While you entered the values in a dictionary in a particular order, a dict doesn't retain any sort of order. .keys() on a dict returns in no particular order. There is an OrderedDict that does retain order, but I don't know how that interacts with Counter.

EDIT:

You may want to use Counter.most_common(). That will return a list of tuples which will be in order.

Tim Tisdall
  • 9,914
  • 3
  • 52
  • 82
2

Another solution without creating an extra class is to take the set of items you have and sort them based on the counted keys. The code below is based on @user3005486:

import collections

#if this is your list    
list_to_be_sorted = ['they', 'would', 'they', ...]
#then counterlist = {'would': 203, 'they': 138, 'your': 134}
counterlist = collections.Counter(list_to_be_sorted)
#if you sort this list ascendingly you get ['would', 'would', ..., 'they', 'they', ...etc.]
sorted_words = sorted(counterlist, key: lambda x:-counterlist[x])
distinct_words_from_list = set(list_to_be_sorted)
sorted_distinct_list = sorted(distinct_words_from_list, key: lambda x:-counterlist[x])
#then sorted_distinct_list = ['would', 'they', 'your']
Bahaa
  • 1,577
  • 18
  • 31
0

The question is from 2016, meanwhile dictionaries in Python guarantee preservation of insertion order in compliance with PEP 468.

From the docs:

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.

so, for Python >= 3.7

counterlist = Counter({'they': 203, 'would': 138, 'your': 134,...})
counterlist.keys()                                                                                                                                           
# Out: dict_keys(['they', 'would', 'your'])

See also: Are dictionaries ordered in Python 3.6+?

user2314737
  • 27,088
  • 20
  • 102
  • 114