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

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

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


当前回答

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

其他回答

我有同样的问题,我这样解决了:

WantedOutput = sorted(MyDict, key=lambda x : MyDict[x]) 

(回答“不可能对字典进行排序”的人没有读到这个问题!事实上,“我可以对键进行排序,但如何根据值进行排序?”显然意味着他想要一个根据其值排序的键列表。)

请注意,顺序没有很好地定义(具有相同值的键在输出列表中的顺序是任意的)。

您还可以创建“反向索引”

from collections import defaultdict
inverse= defaultdict( list )
for k, v in originalDict.items():
    inverse[v].append( k )

现在你的逆函数有了值;每个值都有一个适用的键列表。

for k in sorted(inverse):
    print k, inverse[k]

我刚刚从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')]

从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。

months = {"January": 31, "February": 28, "March": 31, "April": 30, "May": 31,
          "June": 30, "July": 31, "August": 31, "September": 30, "October": 31,
          "November": 30, "December": 31}

def mykey(t):
    """ Customize your sorting logic using this function.  The parameter to
    this function is a tuple.  Comment/uncomment the return statements to test
    different logics.
    """
    return t[1]              # sort by number of days in the month
    #return t[1], t[0]       # sort by number of days, then by month name
    #return len(t[0])        # sort by length of month name
    #return t[0][-1]         # sort by last character of month name


# Since a dictionary can't be sorted by value, what you can do is to convert
# it into a list of tuples with tuple length 2.
# You can then do custom sorts by passing your own function to sorted().
months_as_list = sorted(months.items(), key=mykey, reverse=False)

for month in months_as_list:
    print month