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

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

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


当前回答

在最近的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)])

其他回答

从Python 3.6开始,将订购内置dict

好消息是,OP最初的用例是将从数据库中检索到的具有唯一字符串ID作为关键字和数值作为值的对映射到内置Python v3.6+dict中,现在应该遵循插入顺序。

如果说从数据库查询得到的两列表表达式如下:

SELECT a_key, a_value FROM a_table ORDER BY a_value;

将存储在两个Python元组k_seq和v_seq(按数字索引对齐,当然长度相同)中,然后:

k_seq = ('foo', 'bar', 'baz')
v_seq = (0, 1, 42)
ordered_map = dict(zip(k_seq, v_seq))

允许稍后输出为:

for k, v in ordered_map.items():
    print(k, v)

在这种情况下(对于新的Python 3.6+内置dict!):

foo 0
bar 1
baz 42

按v值的相同顺序排列。

在我的机器上安装Python 3.5时,它当前的结果是:

bar 1
foo 0
baz 42

细节:

正如Raymond Hettinger在2012年提出的(参见主题为“更紧凑的字典,更快的迭代”的python-dev邮件),现在(2016年)Victor Stinner在给python-dev的邮件中宣布的主题为“python 3.6 dict变得紧凑,并获得了私有版本;关键字变得有序”,这是由于python 3.6中第27350期“紧凑和有序的dict”的修复/实现能够使用内置dict来维护插入顺序!!

希望这将导致作为第一步的薄层OrderedDict实现。正如@JimFasarakis Hilliard所指出的,一些人在未来也会看到OrderedDict类型的用例。我认为Python社区将仔细检查,这是否经得起时间的考验,以及下一步将采取什么措施。

是时候重新思考我们的编码习惯了,不要错过稳定排序带来的可能性:

关键字参数和(中间)字典存储

第一个原因是在某些情况下,它简化了函数和方法实现中的调度。

第二,它鼓励更容易地将dict用作处理管道中的中间存储。

雷蒙德·赫廷格(Raymond Hettinger)在其旧金山Python Meetup Group演讲2016-DEC-08中善意地提供了解释“Python3.6词典背后的技术”的文档。

也许相当多的Stack Overflow高修饰问答页面会收到这些信息的变体,许多高质量的答案也需要每个版本的更新。

注意事项Emptor(但也可参见以下更新2017-12-15):

正如@ajcr正确地指出的:“这个新实现的顺序保持方面被认为是一个实现细节,不应该依赖它。”(来自whatsnew36)不是吹毛求疵,但引用有点悲观;-)。它继续为“(这在未来可能会发生变化,但在更改语言规范以强制所有当前和未来Python实现保持顺序的语义之前,希望在语言中使用这个新的dict实现几个版本;这也有助于保持与随机迭代顺序仍然有效的语言旧版本的向后兼容性,例如Python 3.5)。”

因此,正如在一些人类语言(如德语)中,用法塑造了语言,而现在已经宣布了意志。。。在whatsnew36中。

更新2017-12-15:

在发给python开发者列表的邮件中,Guido van Rossum声明:

这样做吧。“听写保持插入顺序”是规则。谢谢

因此,dict插入排序的3.6版CPython副作用现在已成为语言规范的一部分(不再只是实现细节)。正如Raymond Hettinger在讨论中提醒的那样,这条邮件线索还提出了一些与众不同的收藏设计目标。OrderedDict。

尝试以下方法。让我们用以下数据定义一个名为mydict的字典:

mydict = {'carl':40,
          'alan':2,
          'bob':1,
          'danny':3}

如果要按关键字对字典进行排序,可以执行以下操作:

for key in sorted(mydict.iterkeys()):
    print "%s: %s" % (key, mydict[key])

这将返回以下输出:

alan: 2
bob: 1
carl: 40
danny: 3

另一方面,如果想要按值对字典进行排序(如问题中所问),可以执行以下操作:

for key, value in sorted(mydict.iteritems(), key=lambda (k,v): (v,k)):
    print "%s: %s" % (key, value)

此命令的结果(按值对字典进行排序)应返回以下内容:

bob: 1
alan: 2
danny: 3
carl: 40

我刚刚从Python for Everyone学习了相关技能。

您可以使用临时列表来帮助您对词典进行排序:

# Assume dictionary to be:
d = {'apple': 500.1, 'banana': 1500.2, 'orange': 1.0, 'pineapple': 789.0}

# Create a temporary list
tmp = []

# Iterate through the dictionary and append each tuple into the temporary list
for key, value in d.items():
    tmptuple = (value, key)
    tmp.append(tmptuple)

# Sort the list in ascending order
tmp = sorted(tmp)

print (tmp)

如果要按降序排序列表,只需将原始排序行更改为:

tmp = sorted(tmp, reverse=True)

使用列表理解,一行是:

# Assuming the dictionary looks like
d = {'apple': 500.1, 'banana': 1500.2, 'orange': 1.0, 'pineapple': 789.0}
# One-liner for sorting in ascending order
print (sorted([(v, k) for k, v in d.items()]))
# One-liner for sorting in descending order
print (sorted([(v, k) for k, v in d.items()], reverse=True))

样本输出:

# Ascending order
[(1.0, 'orange'), (500.1, 'apple'), (789.0, 'pineapple'), (1500.2, 'banana')]
# Descending order
[(1500.2, 'banana'), (789.0, 'pineapple'), (500.1, 'apple'), (1.0, 'orange')]

为了完整起见,我发布了一个使用heapq的解决方案。注意,此方法适用于数值和非数值

>>> x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
>>> x_items = x.items()
>>> heapq.heapify(x_items)
>>> #To sort in reverse order
>>> heapq.nlargest(len(x_items),x_items, operator.itemgetter(1))
[(3, 4), (4, 3), (1, 2), (2, 1), (0, 0)]
>>> #To sort in ascending order
>>> heapq.nsmallest(len(x_items),x_items, operator.itemgetter(1))
[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]

您可以使用:

sorted(d.items(), key=lambda x: x[1])

这将根据字典中每个条目的值从最小到最大对字典进行排序。

要按降序排序,只需添加reverse=True:

sorted(d.items(), key=lambda x: x[1], reverse=True)

输入:

d = {'one':1,'three':3,'five':5,'two':2,'four':4}
a = sorted(d.items(), key=lambda x: x[1])    
print(a)

输出:

[('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)]