How to create a sorted representation of dictionary, using a custom comparator on tuple values?

admin

Administrator
Staff member
I'm trying to figure out how I can create a sorted representation of a dictionary with values (which are tuples), using with custom comparator on the values in Python 3, <strong>in a generalised way</strong>.

I have read these topics, but I'm still struggling:

<a href="https://stackoverflow.com/questions/613183/sort-a-python-dictionary-by-value">Sort a Python dictionary by value</a>

<a href="https://stackoverflow.com/questions/2531952/how-to-use-a-custom-comparison-function-in-python-3">How to use a custom comparison function in Python 3?</a>

As a <strong>specific example</strong>, one could consider the problem I'm trying to solve as, "get a list of products sorted by total cost, given a dictionary that contains the products (the key) a customer has in their checkout, along with the number and cost of each product (stored as a 2-tuple). In python 2, one could use something like this:

Code:
checkout_dict = {'Apples': (1, 3), 'Oranges': (3, 3), 'Grapes': (7, 1),
                 'Cheese': (10, 1), 'Crackers': (4, 4)}


from operator import itemgetter


def sort_dict(dict, comparison_func):
    return sorted(dict.iteritems(), key=itemgetter(1),
                  cmp=comparison_func)


def cmp_total_cost(product_data_1, product_data_2):
    total_product_cost_1 = (product_data_1[0]) * (product_data_1[0])
    total_product_cost_2 = (product_data_2[0]) * (product_data_2[0])
    return total_product_cost_2 - total_product_cost_1


print sort_dict(checkout_dict, cmp_total_cost)

The expected output would look something like this:

Code:
[('Crackers', (4, 4)), ('Cheese', (10, 1)), ('Oranges', (3, 3)),
 ('Grapes', (7, 1)), ('Apples', (1, 3))]

However in Python 3, the
Code:
cmp
parameter for
Code:
sorted
was deprecated, and instead we need to include the behaviour as part of the
Code:
key
parameter.

I understand that we need to use something like like the <a href="https://docs.python.org/2/library/functools.html" rel="nofollow noreferrer">
Code:
cmp_to_key
function from the
Code:
functools
module</a>, but I can't wrap my head around how I can keep everything generalised. I'm confused about how the
Code:
itemgetter(1)
can be combined with the
Code:
cmp_to_key
function and a custom comparison function.

Also, I understand that with the above example I could easily just loop over the dictionary first, and calculate the total costs, then do the sort, but I'm looking for a general solution I can apply for many different types of comparisons.

<strong>Note</strong>

I'd also like this to be as performant as possible. I found some info that using
Code:
operator.itemgetter
can really help speed things up:
<a href="https://writeonly.wordpress.com/2008/08/30/sorting-dictionaries-by-value-in-python-improved/" rel="nofollow noreferrer">Sorting Dictionaries by Value in Python (improved?)</a>