在Python中对嵌套字典和列表进行排序
我正在尝试对一个包含列表的字典进行排序。例如,如果我有这样的字典:
a = {'q': {3: [4, 2, 7]}, 'a': {1: [5, 45, 11]}, 'e': {23: [11, 45, 2]}}
我希望排序后的输出是:
[(e, {23:[11,45,2}]), (a, {1:[5,45,11]}), (q,{3,[4,2,7]})]
实际上,我是反向排序,使用列表中的第一个项目作为排序的依据。
如果两个列表的第一个项目相同,就像上面那样,我会根据与列表相关的字符串(主键)按字母顺序进行排序。
我不确定在对字典中的列表进行排序时,是否能得到包含字典的元组输出。
我尝试了这段代码:
sorted((x,b.items(), key=lambda x:[1][2]) for x,b in a.items())
但是它出现了语法错误,我搞不清楚哪里出了问题。
3 个回答
我不是百分之百确定,但你最终想要的是什么呢?
>>> a = {'q': {3: [4, 2, 7]}, 'a': {1: [5, 3, 11]}, 'e': {23: [11, 45, 2]}}
>>> new_order = sorted(a, key=lambda L: a[L].values(), reverse=True)
>>> zip(new_order, map(a.get, new_order))
[('e', {23: [11, 45, 2]}), ('a', {1: [5, 3, 11]}), ('q', {3: [4, 2, 7]})]
至少在交互式解释器中,完整的错误信息会告诉你错误发生的具体位置:
>>> sorted((x,b.items(), key=lambda x:[1][2]) for x,b in a.items())
File "<stdin>", line 1
sorted((x,b.items(), key=lambda x:[1][2]) for x,b in a.items())
^
SyntaxError: invalid syntax
注意到那个 ^
是正好在 =
的下面。
这并不能告诉你为什么会在这里出错,但至少能告诉你该往哪里看。
仔细观察后,你会发现这个子表达式:
(x,b.items(), key=lambda x:[1][2])
这是一个元组,它的第三个元素是 key=lambda x:[1][2]
。但是,这个表达式是无效的。所以,你的括号放错地方了。或者说,你把 key
参数放错了位置。我想你应该是想这样:
sorted(((x,b.items()) for x,b in a.items()), key=lambda x:[1][2])
那里没有 SyntaxError
。看起来后面会出现一个 IndexError
,但你可以等到那时候再处理。
我们把这个问题拆开来看。你其实是想对列表 a.items()
进行排序。那么:
>>> to_sort = a.items()
>>> to_sort
[('q', {3: [4, 2, 7]}), ('a', {1: [5, 3, 11]}), ('e', {23: [11, 45, 2]})]
对于列表中的每个元素,你会得到一个包含值(比如 'q'
等)和一个字典的元组。可以想象每个字典里只有一个键,而你想用每个字典值的第一个索引(也就是第二个元素)作为主要的排序依据。所以,第一个元素的排序关键字应该是: to_sort[0][1].values()[0][1]
。这里 to_sort[0][1]
会给你字典 {3: [4, 2, 7]}
,而 .values()
会得到列表 [[4, 2, 7]]
,接着 [0][1]
就会得到 2
。第二个排序关键字就是简单的 to_sort[0]
。
所以我们得到:
>>> sorted(to_sort, key=lambda x: (x[1].values()[0][1], x[0]))
[('q', {3: [4, 2, 7]}), ('a', {1: [5, 3, 11]}), ('e', {23: [11, 45, 2]})]
我们快完成了。现在你只需要告诉排序函数你想要反向输出:
>>> sorted(to_sort, key=lambda x: (x[1].values()[0][1], x[0]), reverse=True)
[('e', {23: [11, 45, 2]}), ('a', {1: [5, 3, 11]}), ('q', {3: [4, 2, 7]})]
这就是你想要的吗?
如果你想要一行代码搞定,可以这样写:
>>> sorted(a.items(), key=lambda x: (x[1].values()[0][1], x[0]), reverse=True)