3

I have a dictionary with objects as values. These objects are instances of the following class:

Class A():

    def __init__(self, x=''):
        self.x = x
        self.count = 0

The dictionary entries will therefore be of the form: {'some_key', instance_of_class_A}

Now, I would like to sort the dictionary on the the value of A.count within the instance_of_A.

I have failed to find an answer to this through numerous searches so am hoping someone has solved this before! Thanks P.

jpp
  • 159,742
  • 34
  • 281
  • 339
Paul
  • 813
  • 11
  • 27
  • 1
    What do you mean by "sort the dictionary"? Dictionaries are inherently unordered, even in Python 3.7, where the *iteration* order is guaranteed to match the order in which the keys were inserted. – chepner Nov 28 '18 at 13:51
  • I understand that yes, but I would like to order the dictionary. And I need this ordering to be based on the value of the object field. – Paul Nov 28 '18 at 13:53
  • `{'some_key', instance_of_class_A}` does not look like a dictionary - do you mean `{'some_key': instance_of_class_A}` and are these dictionary entries in a list? can you show an example? also, please include what you have tried so far. – Sina Khelil Nov 28 '18 at 13:56

3 Answers3

2

To sort the values of a dictionary, you can do the following:

sorted_values = sorted(dict.values(), key=lambda x: x.count)

I do not see the need for sorting an entire dictionary, however. If the key value can hold a list of A objects and you want to sort that:

dict[key] = sorted(dict[key], key=lambda x: x.count)
SBylemans
  • 1,764
  • 13
  • 28
1

Assuming you are using a version of Python that provides for guaranteed ordering, you need to create a new dict, inserting the elements in the proper order.

old_dict = { ... }
new_dict = dict(sorted(old_dict.items(), key=lambda kv: kv[1].count))
chepner
  • 497,756
  • 71
  • 530
  • 681
  • 1
    It should be noted that this is only guaranteed on 3.7+, but also works on 3.5 and 3.6 as the result of an implementation detail. This difference means that on non-CPython implementations of 3.5 and 3.6 this may not work. – Dunes Nov 28 '18 at 14:33
  • 2
    Does it work in CPython 3.5? I thought that implementation wasn't added until 3.6. – chepner Nov 28 '18 at 14:38
1

While dictionaries are insertion-ordered in Python 3.6 (as an implementation detail) and officially in 3.7+, for a robust ordered dictionary use collections.OrderedDict:

from collections import OrderedDict

res = OrderedDict(sorted(d.items(), key=lambda x: x[1].count))

OrderedDict is a subclass of dict, so you should lose no functionality.

If such an ordering is natural or typical to your class objects, consider defining __eq__ and __lt__ methods to your class as described here and then use:

from operator import itemgetter

res = OrderedDict(sorted(d.items(), key=lambda x: x[1]))
res = OrderedDict(sorted(d.items(), key=itemgetter(1)))  # functional equivalent
jpp
  • 159,742
  • 34
  • 281
  • 339