Сортировать вложенный словарь по переменному количеству ключей - PullRequest
0 голосов
/ 09 июля 2019

Я пытаюсь отсортировать диктант по нескольким ключам.Вот что у меня есть:

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}}

Я хочу отсортировать его в следующем порядке: 'points', 1, 2, 3, 4, 5.

Я мог бы сделатьэто, я предполагаю:

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

Однако клавиши 1, 2, 3, 4, 5 являются динамическими (и могут быть 1, 2, 3, 4, 5, 6, 7, 8, 9и т. д.)

Итак, каким-то образом я хочу сделать ключи сортировки динамическими в sorted(), за исключением 'points', который всегда будет использоваться.

Результат, который я хочу получить, является обратнымотсортированный список с ключами (которые являются идентификаторами игроков из БД) из первого dict.т.е. для данного примера это будет [2, 1, 3].

1 Ответ

1 голос
/ 09 июля 2019

По сути, вы ищете itemgetter с 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]

Объяснение:

Чтобы выполнить сортировку по нескольким ключам, вы можете использовать itemgetter, чтобы создать функцию, которая будет возвращать кортеж значений по указанным ключам.Итак, в качестве простого примера, если у вас будет этот словарь:

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

, и вы захотите получить значения по ключам player, 1 и 2, вы должны написать:

from operator import itemgetter

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

Теперь, поскольку количество значений может варьироваться и это фактически упорядоченные целые числа (1, 2, 3, ...), вы можете распаковать заданное rangeв itemgetter:

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

Наконец, для вашего данного примера словаря словарей мы получаем эти кортежи для каждого дочернего словаря и сортируем по ним:

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]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...