按可变数量的键对嵌套字典进行排序

时间:2019-07-09 07:55:29

标签: python sorting dictionary nested

我正在尝试通过多个键对字典进行排序。这是我的命令:

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'

我想要的结果是一个反向排序的列表,其中包含第一个字典中的键(数据库中的播放器ID)。也就是说,对于给定的示例,它将为[2, 1, 3]

1 个答案:

答案 0 :(得分:1)

基本上,您正在寻找的是itemgetterrange

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]

说明:

为了通过几个dict键进行排序,可以使用itemgetter创建一个函数,该函数将通过指定的键返回一个元组值。因此,举一个简单的例子,如果您有这本字典:

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

,并且您想通过键player12来获取值,您将编写:

from operator import itemgetter

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

现在,由于值的数量可以变化并且它们实际上是有序整数(1、2、3,...),因此您可以unpack将给定的range设置为{{1 }}:

itemgetter

最后,对于给定的示例词典字典,我们为每个子词典获取这些元组并按它们排序:

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