ShanghaiD
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:
I've tried:
Can anyone point me in the right direction to solve my problem?
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}
]
}
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'))
and grid['EM'].sort(key=lambda item:(grid['EM']['date'], grid['EM']['sort']))
but neither work.Can anyone point me in the right direction to solve my problem?
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
@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.
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.
ASKER