Link to home
Start Free TrialLog in
Avatar of ShanghaiD
ShanghaiDFlag for United Kingdom of Great Britain and Northern Ireland

asked on

Python: sort dictionary of dictionaries

I'm running Python 2.7 and am still learning the language.

I know that sorting a dictionary is not the same as sorting a list (which I can do).

I have a dictionary of dictionaries, as follows:

grid = {'EM':
  [
        {'date': 20081108, 'amount': -216846, 'sort': 2},
	{'date': 20110608, 'amount': 0, 'sort': 2},
	{'date': 20130703, 'amount': 6894997, 'sort': 0},
	{'date': 20131206, 'amount': -94478, 'sort': 2},
	{'date': 20100114, 'amount': 14959, 'sort': 0},
	{'date': 20100508, 'amount': 0, 'sort': 2},
	{'date': 20131224, 'amount': -99513, 'sort': 3},
	{'date': 20060808, 'amount': -23, 'sort': 2},
	{'date': 20090921, 'amount': -119229, 'sort': 3}
  ]
}

Open in new window

I want to sort the nested dictionary items by 'date' and then by 'sort' so grid['EM'][0] becomes {'date': 20060808, 'amount': -23, 'sort': 2} instead of  {'date': 20081108, 'amount': -216846, 'sort': 2}

I've tried:
grid['EM'].sort(key=lambda item:('date', 'sort'))

Open in new window

and
grid['EM'].sort(key=lambda item:(grid['EM']['date'], grid['EM']['sort']))

Open in new window

but neither work.

Can anyone point me in the right direction to solve my problem?
ASKER CERTIFIED SOLUTION
Avatar of aikimark
aikimark
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of ShanghaiD

ASKER

Thank you!  I will read more about lambda sorts in Python to understand more about the alternative syntax options.
Avatar of pepr
pepr

@ShanghaiD: The sort() or sorted() functions can be passed a function that says what is the key of the element. The aikimark's solution concatenates two items of the dictionary: date and sort. When sorting it lexicographically, you get the result.

However, there is a bug in the solution. Firstly, the date and sort values should be converted to strings first. And also, if the sort element of the inner dictionary can be bigger than 9, then the sorting will fail. The reason is that 10 is lexicographically smaller than 9, for example. So, the sort value should be left padded by zeros like:  str(x['date']) + str(x['sort']).zfill(5).

Alternatively, you can multiply the date number not to mix its content with the sort number. Then no str() is needed: x['date'] * 10000 + x['sort'].

The lambda is just "unnamed, temporary" function that does the composition (here with one argument x that is the inner dictionary). The same way, you could define your own named function. However, the body of the function is so simple that it would add more lines than necessary.
For variable length data, I usually insert a delimiter character between the constructed sort key values.  I like to use the carrot character (^), but any character not found in either of the two component fields will do.