我有一个从数据库中两个字段读取的值字典:字符串字段和数字字段。字符串字段是唯一的,因此它是字典的关键字。

我可以按关键字排序,但如何根据值排序?

注意:我在这里读过堆栈溢出问题。如何根据字典的值对字典列表进行排序?并且可能会更改我的代码,使其具有字典列表,但由于我确实不需要字典列表,我想知道是否有更简单的解决方案来按升序或降序排序。


当前回答

Python 3.7+或CPython 3.6

Python 3.7+中的字典保持插入顺序。CPython 3.6中也一样,但这是一个实现细节。

>>> x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
>>> {k: v for k, v in sorted(x.items(), key=lambda item: item[1])}
{0: 0, 2: 1, 1: 2, 4: 3, 3: 4}

or

>>> dict(sorted(x.items(), key=lambda item: item[1]))
{0: 0, 2: 1, 1: 2, 4: 3, 3: 4}

较旧的Python

不可能对字典进行排序,只能获得已排序字典的表示。字典本质上是无序的,但其他类型,如列表和元组,则不是。因此,您需要一个有序的数据类型来表示排序的值,这将是一个列表,可能是一个元组列表。

例如,

import operator
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=operator.itemgetter(1))

sorted_x将是由每个元组中的第二个元素排序的元组列表。dict(sorted_x)==x。

对于那些希望按关键字而不是值排序的用户:

import operator
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=operator.itemgetter(0))

在Python3中,由于不允许开箱,我们可以使用

x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=lambda kv: kv[1])

如果要将输出作为字典,可以使用collections.OrderedDict:

import collections

sorted_dict = collections.OrderedDict(sorted_x)

其他回答

使用Python 3.5

虽然我发现公认的答案很有用,但我也感到惊讶的是,它还没有更新,以引用标准库集合模块中的OrderedDict作为一种可行的现代替代方案-旨在解决这类问题。

from operator import itemgetter
from collections import OrderedDict

x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = OrderedDict(sorted(x.items(), key=itemgetter(1)))
# OrderedDict([(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)])

官方OrderedDict文档也提供了一个非常类似的示例,但使用lambda作为排序函数:

# regular unsorted dictionary
d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}

# dictionary sorted by value
OrderedDict(sorted(d.items(), key=lambda t: t[1]))
# OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])

如果值是数字,则还可以使用集合中的计数器。

from collections import Counter

x = {'hello': 1, 'python': 5, 'world': 3}
c = Counter(x)
print(c.most_common())

>> [('python', 5), ('world', 3), ('hello', 1)]    

字典无法排序,但您可以根据它们构建排序列表。

字典值的排序列表:

sorted(d.values())

按值排序的(键、值)对列表:

from operator import itemgetter
sorted(d.items(), key=itemgetter(1))

在最近的Python2.7中,我们有了新的OrderedDict类型,它可以记住添加项目的顺序。

>>> d = {"third": 3, "first": 1, "fourth": 4, "second": 2}

>>> for k, v in d.items():
...     print "%s: %s" % (k, v)
...
second: 2
fourth: 4
third: 3
first: 1

>>> d
{'second': 2, 'fourth': 4, 'third': 3, 'first': 1}

要从原始字典创建新的有序字典,请按值排序:

>>> from collections import OrderedDict
>>> d_sorted_by_value = OrderedDict(sorted(d.items(), key=lambda x: x[1]))

OrderedDict的行为类似于普通dict:

>>> for k, v in d_sorted_by_value.items():
...     print "%s: %s" % (k, v)
...
first: 1
second: 2
third: 3
fourth: 4

>>> d_sorted_by_value
OrderedDict([('first': 1), ('second': 2), ('third': 3), ('fourth': 4)])

另一个答案中提到的集合解决方案绝对是极好的,因为您在键和值之间保留了一种联系,这在字典中是极其重要的。

我不同意另一个答案中的第一选择,因为它会扔掉钥匙。

我使用了上面提到的解决方案(代码如下所示),并保留了对键和值的访问权,在我的情况下,排序是对值进行的,但重要的是对值排序后的键排序。

from collections import Counter

x = {'hello':1, 'python':5, 'world':3}
c=Counter(x)
print( c.most_common() )


>> [('python', 5), ('world', 3), ('hello', 1)]