0

I'm trying to sort a dict by multiple keys. This is the dict I have:

standings = {1: {1: 1, 2: 0, 3: 1, 4: 0, 5: 0, 'player': 'Jack', 'points': 15}, 2: {1: 1, 2: 0, 3: 2, 4: 2, 5: 0, 'player': 'Kate', 'points': 15}, 3: {1: 0, 2: 0, 3: 1, 4: 0, 5: 0, 'player': 'Sawyer', 'points': 5}} 

I want to sort it by, in this order: 'points', 1, 2, 3, 4, 5.

I could do this, I assume:

reversed(sorted(standings, key=lambda x: (standings[x]['points'], standings[x][1], standings[x][2], standings[x][3], standings[x][4], standings[x][5]))) 

However, the 1, 2, 3, 4, 5 keys are dynamic (and could be 1, 2, 3, 4, 5, 6, 7, 8, 9, etc.)

So, somehow I want to make the sorting keys dynamic in sorted(), except for 'points' which will always be used.

The result I want is a reversed sorted list with the keys (which are player ids from the db) from the first dict. i.e. for the given example it will be[2, 1, 3].

1

1 Answer 1

1

Basically, what you are looking for is itemgetter with range:

from operator import itemgetter standings = ... # your dictionary of dictionaries n = 5 # number of keys to sort on (1, 2, 3, ..., n) # The following will collect values by 'points', 1, 2, ..., n in a tuple: get_values = itemgetter('points', *range(1, n + 1)) result = sorted(standings, key=lambda x: get_values(standings[x]), reverse=True) # [2, 1, 3] 

Explanation:

In order to achieve the sorting by several dict keys, you could use itemgetter to create a function that will return a tuple of values by specified keys. So, as a simple example, if you would have this dictionary:

my_dict = {1: 10, 2: 20, 3: 30, 4: 40, 5: 50, 'player': 'Ben'} 

and you would want to get the values by keys player, 1 and 2, you would write:

from operator import itemgetter get_values = itemgetter('player', 1, 2) get_values(my_dict) # ('Ben', 10, 20) 

Now, as the number of the values can vary and those are actually ordered integers (1, 2, 3, ...), you could unpack the given range to the itemgetter:

get_values = itemgetter('player', *range(1, 4)) # 'player', 1, 2, 3 get_values(my_dict) # ('Ben', 10, 20, 30) 

Finally, for your given example dictionary of dictionaries we get these tuples for each child dictionary and sort by them:

standings = {1: {1: 1, 2: 0, 3: 1, 4: 0, 5: 0, 'player': 'Jack', 'points': 15}, 2: {1: 1, 2: 0, 3: 2, 4: 2, 5: 0, 'player': 'Kate', 'points': 15}, 3: {1: 0, 2: 0, 3: 1, 4: 0, 5: 0, 'player': 'Sawyer', 'points': 5}} max_key = 5 # you may also calculate it as a max integer key get_values = itemgetter('points', *range(1, n + 1)) result = sorted(standings, key=lambda x: get_values(standings[x])) # [3, 1, 2] # or reversed: sorted(standings, key=lambda x: get_keys(standings[x]), reverse=True) # [2, 1, 3] 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.