Python 3 按其值对字典进行排序

Posted

技术标签:

【中文标题】Python 3 按其值对字典进行排序【英文标题】:Python 3 sort a dict by its values 【发布时间】:2014-01-23 12:47:51 【问题描述】:

我发现的唯一方法适用于 python2 或仅返回元组列表。

是否可以对字典进行排序,例如"aa": 3, "bb": 4, "cc": 2, "dd": 1,通过它的价值观?

我想要实现的排序字典的顺序是从大到小。我希望结果如下所示:

bb 4
aa 3
cc 2
dd 1

排序后我想将它存储到一个文本文件中。

【问题讨论】:

【参考方案1】:

itemgetter(见其他答案)(据我所知)对于大型字典更有效,但对于常见情况,我相信d.get 获胜。而且它不需要额外的import

>>> d = "aa": 3, "bb": 4, "cc": 2, "dd": 1
>>> for k in sorted(d, key=d.get, reverse=True):
...     k, d[k]
...
('bb', 4)
('aa', 3)
('cc', 2)
('dd', 1)

请注意,您也可以将d.__getitem__ 设置为key 函数,这可能会比d.get 提供小的性能提升。

【讨论】:

能否解释一下|展开第 2 行的语法?我刚刚学习 Python 3,很想了解这个。 当然,但如果我知道你不明白的地方会更容易。 [x for x in iterable] 是一个 Python List Comprehension (google),它在 Python 中创建列表非常常见且高效。 (k, d[k]) 是一个双元素元组,第二个元素 (d[k]) 是字典中的值。 sorted() 是一个内置函数,返回按值排序的字典键。使用key=d.get 它是我的答案的关键,这并不容易知道。了解内置函数是必不可少的。我希望这会有所帮助。 谢谢! [x for x in iterable]“列表理解”是介绍课程中缺少的内容。现在阅读它(很难找到不知道名字的)。 我通过最后一次编辑使代码更简单,完全消除了列表理解。【参考方案2】:
from collections import OrderedDict
from operator import itemgetter    

d = "aa": 3, "bb": 4, "cc": 2, "dd": 1
print(OrderedDict(sorted(d.items(), key = itemgetter(1), reverse = True)))

打印

OrderedDict([('bb', 4), ('aa', 3), ('cc', 2), ('dd', 1)])

尽管从您的最后一句话来看,元组列表似乎可以正常工作,例如

from operator import itemgetter  

d = "aa": 3, "bb": 4, "cc": 2, "dd": 1
for key, value in sorted(d.items(), key = itemgetter(1), reverse = True):
    print(key, value)

打印出来的

bb 4
aa 3
cc 2
dd 1

【讨论】:

感谢您的帮助。我认为其中一个解决方案将与此类似。 dict 现在保持插入顺序,因此没有理由使用OrderedDict 我可以想到两个原因,首先它明确表明您关心订单,其次有人可能会在较旧的解释器上运行您的代码,并且让它默默地行为不端并不是一个好的结果。【参考方案3】:

您可以使用dictionary comprehension以反向顺序(从大到小)按排序:

k: d[k] for k in sorted(d, key=d.get, reverse=True)
# 'b': 4, 'a': 3, 'c': 2, 'd': 1

如果您想按升序(从小到大)排序

k: d[k] for k in sorted(d, key=d.get)
# 'd': 1, 'c': 2, 'a': 3, 'b': 4

如果要按升序排序

k: d[k] for k in sorted(d)
# 'a': 3, 'b': 4, 'c': 2, 'd': 1

这适用于 CPython 3.6+ 和 Python 3.7+ 的任何实现,因为字典保持插入顺序。

【讨论】:

【参考方案4】:

另一种方法是使用 lambda 表达式。根据解释器版本以及您是否希望创建排序字典或排序键值元组(如 OP 所做的那样),这甚至可能比接受的答案更快。

d = 'aa': 3, 'bb': 4, 'cc': 2, 'dd': 1
s = sorted(d.items(), key=lambda x: x[1], reverse=True)

for k, v in s:
    print(k, v)

【讨论】:

虽然您的代码可以正常工作,但我认为字典不能保证按照添加的顺序返回项目。 @Ivan 谢谢——我已经删除了这里多余的 dict() 用法,尽管在 CPython 3.6+ 中,dict 是保持顺序的,这很可能在不久的将来成为一种语言特性(docs.python.org/3/whatsnew/3.6.html) 谢谢,很高兴知道。另外 - 最后你可以只做print(s) 而不是循环:) dicts 保留从 3.7 开始的所有 Python 的顺序 实际上它不到 10%,我在 Python 3.8.6 上用 100,000 个元素的字典得到 54 毫秒和 57.3 毫秒,但在技术上仍然较慢。我认为您应该删除它们,这不是值得优化的。【参考方案5】:

要对字典进行排序,我们可以使用 operator 模块。 Here 是操作员模块文档。

import operator                             #Importing operator module
dc =  "aa": 3, "bb": 4, "cc": 2, "dd": 1  #Dictionary to be sorted

dc_sort = sorted(dc.items(),key = operator.itemgetter(1),reverse = True)
print dc_sort

输出序列将是一个排序列表:

[('bb', 4), ('aa', 3), ('cc', 2), ('dd', 1)]

如果我们想对键进行排序,我们可以使用

dc_sort = sorted(dc.items(),key = operator.itemgetter(0),reverse = True)

输出序列将是:

[('dd', 1), ('cc', 2), ('bb', 4), ('aa', 3)]

【讨论】:

Paul Draper 的回答已经在使用 Operator...只是没有导入完整的库【参考方案6】:

要对字典进行排序并在之后保持它作为字典的功能,您可以使用标准库中的OrderedDict。

如果这不是您所需要的,那么我鼓励您重新考虑给您留下元组列表的排序函数。如果不是键值对(元组)的有序列表,您想要什么输出?

【讨论】:

dict 现在保持插入顺序,因此没有理由使用OrderedDict

以上是关于Python 3 按其值对字典进行排序的主要内容,如果未能解决你的问题,请参考以下文章

Facet_wrap 未按其值正确排序图

java 根据其值对地图进行排序。资料来源:http://stackoverflow.com/a/2581754/1057348

如何根据其值的属性对地图进行排序?

Jquery 选择器按其值获取下拉列表

按其值将任何结构字段名称转换为字符串

如果给定@RequestParameter,则按其值过滤,如果没有,则不执行任何操作[重复]