Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort nested dictionary by value, and remainder by another value, in Python

People also ask

How do you sort a value in nested dictionary python?

Method #1 : Using OrderedDict() + sorted() This task can be performed using OrderedDict function which converts the dictionary to specific order as mentioned in its arguments manipulated by sorted function in it to sort by the value of key passed.

How do you sort dictionaries by dictionary value?

To sort a list of dictionaries according to the value of the specific key, specify the key parameter of the sort() method or the sorted() function. By specifying a function to be applied to each element of the list, it is sorted according to the result of that function.


Use the key argument for sorted(). It lets you specify a function that, given the actual item being sorted, returns a value that should be sorted by. If this value is a tuple, then it sorts like tuples sort - by the first value, and then by the second value.

sorted(your_list, key=lambda x: (your_dict[x]['downloads'], your_dict[x]['date']))

You can pass a key function to sorted which returns a tuple containing the two things you wish to sort on. Assuming that your big dictionary is called d:

def keyfunc(tup):
    key, d = tup
    return d["downloads"], d["date"]

items = sorted(d.items(), key = keyfunc)

You can do this with a lambda if you prefer, but this is probably more clear. Here's the equivalent lambda-based code:

items = sorted(d.items(), key = lambda tup: (tup[1]["downloads"], tup[1]["date"]))

Incidentally, since you mentioned that you wanted to sort by "downloads" first, the above two examples sort according to download counts in ascending order. However, from context it sounds like you might want to sort in decreasing order of downloads, in which case you'd say

return -d["downloads"], d["date"]

in your keyfunc. If you wanted something like sorting in ascending order for non-zero download numbers, then having all zero-download records after that, you could say something like

return (-d["downloads"] or sys.maxint), d["date"]

My other answer was wrong (as are most of the answers here)

sorted_keys = sorted((key for key in outer_dict if outer_dict[key]['downloads']),
                     key=lambda x: (outer_dict[key]['downloads'],
                                    outer_dict[key]['downloads'])
                     reverse=True)

sorted_keys += sorted((key for key in outer_dict if not outer_dict[key]['downloads']),
                      key=lambda x: outer_dict[key]['date'])

This will create a list with the items that have been downloaded sorted in descending order at the front of it and the rest of the items that have not been downloaded sorted by date after those that have.

But actually, the last part of Eli Courtwrights answer is the best.


a = {'KEY1':{'name':'google','date':20100701,'downloads':0},
 'KEY2':{'name':'chrome','date':20071010,'downloads':0},
 'KEY3':{'name':'python','date':20100710,'downloads':100}}


z = a.items()

z.sort(key=lambda x: (x[1]['downloads'], x[1]['date']))