Gerri Gerri - 4 months ago 35
Python Question

Python sort (json) list by calculated value

I have originally a JSON format with products and the challenge is to sort this list by the best price per unit (prdata3, prdata2, prdata1):

{'prdata3': {'variation': 'stand', 'price': '78 54', 'amount': '6',
'url': ''},
'prdata2': {'variation': 'stand', 'price': '15 24', 'amount': '1',
'url': ''},
'prdata1': {'variation': 'vc', 'price': '78 54', 'amount': '12',
'url': ''}}

The price needs to be divided by the amount and the list needs to be sorted by this value, so in my example the output need to be (prdata1 (6,55), prdata3 (13,09), prdata2 (15,24)):

{'prdata1': {'variation': 'vc', 'price': '78 54', 'amount': '12', 'url': ''}, 'prdata3': {'variation': 'stand', 'price': '78 54', 'amount': '6', 'url': ''}, 'prdata2': {'variation': 'stand', 'price': '15 24', 'amount': '1', 'url': ''}}

What is the best strategy here? I gave my best to first go in there with "for each", looking for the price, replace the space with a dot, divide it with the amount and now use this result to sort my list with something like:
sorted(mylist.items(), key=lambda t: t[1])
... but my result as key, right?


You can't sort a dictionary, as dictionary have no order.

But you can do the following:

print sorted(a.items(),key=lambda x:float(x[1]['price'])/int(x[1]['amount']))


[('prdata1', {'url': '', 'price': '78.54', 'amount': '12', 'variation': 'vc'}), 
('prdata3', {'url': '', 'price': '78.54', 'amount': '6', 'variation': 'stand'}), 
('prdata2', {'url': '', 'price': '15.24', 'amount': '1', 'variation': 'stand'})]

And, you can use collections.OrderedDict to retain the dictionary structure if it really matters.

from collections import OrderedDict
print OrderedDict(sorted(a.items(),key=lambda x:float(x[1]['price'])/int(x[1]['amount'])))


OrderedDict([('prdata1', {'url': '', 'price': '78.54', 'amount': '12', 'variation': 'vc'}), 
('prdata3', {'url': '', 'price': '78.54', 'amount': '6', 'variation': 'stand'}), 
('prdata2', {'url': '', 'price': '15.24', 'amount': '1', 'variation': 'stand'})])