How to create a list of keys in a nested dictionary based on two conditions?

Viewed 97

Let's say we have a dictionary:

 m_dict = {'2011-04-01': {'asprin': (232, -7, -4, 1), 'glucose': (3, 4, -3)},
           '2011-04-02': {'clb': (-7, -2, 8), 'humulin': (3, -6, -3), 'crack': (7,-5)},
           '2011-04-03': {'otc': (-1, 34, -45), 'tussin': (-2, 8)} }

I'm trying to sort this dictionary in decending order based on the number of drugs a date holds, but if two dates have the same number of drugs then sort those dates in ascending order. So, the list in this case should be: ['2011-04-02', '2011-04-01', '2011-04-03'].

I understand how to sort based on the number of drugs, but confused on how to implement another sorting condition if the number of drugs are the same.

Something like this? I'm trying to do it in a single statement using combinations of comprehension. But this doesn't apply the rule: if the number of drugs is the same for two dates, then sort those two dates in date_lst in ascending order.

date_lst = [key for key in sorted(m_dict.keys(), key = lambda item[key]): len(item[key]))
3 Answers

You can sort the list by a tuple of values, the length of the dictionary element (negated to sort descending) and then the key:

date_lst = [key for key in sorted(m_dict.keys(), key=lambda k: (-len(m_dict[k]), k))]

Output:

['2011-04-02', '2011-04-01', '2011-04-03']

Note that you can just use m_dict rather than m_dict.keys() since sorted operates on the keys when sorting a dict, not the values (since that's what dict returns as an iterator). So you can simplify to:

date_lst = [key for key in sorted(m_dict, key=lambda k: (-len(m_dict[k]), k))]

Try this code.

sorted_key_list = sorted(m_dict.keys(), key = lambda t:len(m_dict[t].items()))

If you want to make dictionary with order, use collections.OrderDict as follows.

from collections import OrderedDict
sorted_dic = OrderedDict()
for key in sorted_key_list:
    sorted_dic[key] = m_dict[key]

answered already, just throwing in the itemgetter operator option :

from operator import itemgetter

sorted([(key,len(value))[0] 
        for key,value in m_dict.items()]
       ,key=itemgetter(1),reverse=True)


['2011-04-01', '2011-04-02', '2011-04-03']
Related