如何按值对字典排序?


3422

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

我可以对键进行排序,但是如何根据值进行排序?

注意:我在这里阅读了堆栈溢出问题,如何按字典值对字典列表进行排序?可能会更改我的代码以包含字典列表,但是由于我实际上并不需要字典列表,因此我想知道是否存在一种更简单的解决方案来按升序或降序进行排序。


9
字典数据结构没有固有的顺序。您可以对其进行遍历,但是没有任何保证可以确保迭代遵循任何特定顺序。这是设计使然,所以最好的选择是使用更好的数据结构来表示。
Daishiman

135
“ sorted()”可以对字典进行操作(并返回已排序键的列表),所以我认为他已经意识到这一点。不知道他的程序,告诉别人他们使用了错误的数据结构是荒谬的。如果90%的时间都需要快速查找,那么您可能想要一个字典。
bobpaul

此处以简洁明了的方式介绍了用于排序字典的所有三个输出(键,值,两者):stackoverflow.com/questions/16772071/sort-dict-by-value-python
JStrahl,2016年

2
@Daishiman基类可能不是有序的,但是OrderedDict当然是有序的。
泰勒·埃德米斯顿

1
在Python 3.6+中,字典保留插入顺序。当然,这与按值对它们进行排序的可能性不同,但是,另一方面,说“词典数据结构没有固有顺序”已不再有效。
Konrad Kocik '18年

Answers:


4944

Python 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}

旧版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中,由于不允许拆包[1],我们可以使用

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)

43
针对各种词典排序的定时由值方案: writeonly.wordpress.com/2008/08/30/...
格雷格林德

164
sorted_x.reverse()将给您降序排列(通过第二个tuple元素)
saidimu apale 2010年

414
saidimu:由于我们已经在使用sorted(),所以传递reverse=True参数的效率要高得多。
rmh 2010年

121
在python3我用的λ: sorted(d.items(), key=lambda x: x[1])。可以在python 2.x中使用吗?
Keyo

84
OrderedDict已在2.7中添加到集合中。排序示例显示在:docs.python.org/library/…– 2011
星期一

1262

简单如: sorted(dict1, key=dict1.get)

好吧,实际上可以执行“按字典值排序”。最近,我不得不在Code Golf(堆栈溢出问题Code golf:单词频率图表)中进行此操作。简而言之,问题是这样的:给定文本,计算遇到每个单词的频率,并显示按频率递减排序的最重要单词列表。

如果您以单词为键构建字典,每个单词的出现次数为值,则简化为:

from collections import defaultdict
d = defaultdict(int)
for w in text.split():
    d[w] += 1

那么您可以获取单词列表,sorted(d, key=d.get)并按使用频率排序-使用单词出现的次数作为排序键,对字典键进行排序迭代。

for w in sorted(d, key=d.get, reverse=True):
    print(w, d[w])

我正在写这个详细的说明,以说明人们通常所说的“我可以很容易地按键对字典进行排序,但是如何按值进行排序”的意思-我认为原始帖子试图解决这样的问题。解决方案是根据值对键列表进行排序,如上所示。


31
这也很好,但key=operator.itemgetter(1)效率应具有更大的可扩展性,而不是key=d.get
smci 2011年

3
@raylu我确实使用itemgetter观察到“不起作用”的行为:----- from operator import itemgetter d = {"a":7, "b":1, "c":5, "d":3} sorted_keys = sorted(d, key=itemgetter, reverse=True) for key in sorted_keys: print "%s: %d" % (key, d[key]) ------> b:1 c:5 a:7 d:3每次我运行代码,结果都会改变:很奇怪。(对不起,无法正确显示代码)
bli

12
@bli sorted_keys = sorted(d.items(), key=itemgetter(1), reverse=True)和-itemgetter for key, val in sorted_keys: print "%s: %d" % (key, val)在调用时会创建一个函数,您不会像在示例中那样直接使用它。字典上的普通迭代使用不带值的键
Izkata 2014年

18
我是从未来来告诉您的collections.Counter,它的一种most_common方法可能会让您感兴趣:)
Eevee

2
@Eevee-在非f2f简短评论中有被误解的风险。Amuzing tidbit:collections.Counter在2.7中添加,几乎是7年前发布的!(那时我还不知道它-再加上为了简洁起见,我会在代码高尔夫球中避免使用它,这是游戏唯一的困扰)
Nas Banov

857

您可以使用:

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)]

根据我所见(docs.python.org/2/library/…),有一个名为OrderedDict的类,可以对它进行排序并保留顺序,同时仍然是字典。从代码示例中,您可以使用lambda对其进行排序,但我还没有亲自尝试过:P
UsAndRufus 2013年

53
key=lambda (k, v): v个人更喜欢
Claudiu 2015年

35
@Claudiu我也喜欢这种(k, v)语法,但是在删除了元组参数解包的 Python 3中它不可用。
鲍勃·斯坦因

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

3
号创建从元组的排序列表的字典再次杀死...的顺序
让·弗朗索瓦·法布尔

233

字典无法排序,但您可以从中建立排序列表。

字典值的排序列表:

sorted(d.values())

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

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

具有相同值的键按什么顺序排列?我先按键,然后按值对列表进行排序,但是不保留具有相同值的键的顺序。
SabreWolfy 2012年

1
现在可以对字典进行排序,从CPython 3.6开始,从3.7开始的所有其他Python实现
Boris

161

在最近的Python 2.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的行为类似于普通字典:

>>> 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)])

5
这不是问题所在,不是维护键的顺序而是“按值排序”
Nas Banov

10
@Nas Banov:它不是按键排序的。它按顺序排序,我们创建项目。在本例中,我们按值排序。不幸的是,不幸的是选择了3个项目dict,所以当按值和键对它们进行排序时,顺序是相同的,所以我扩展了示例dict。
mykhal

sorted(d.items(), key=lambda x: x[1])您能解释一下x为什么可以使用x[1]lambda吗?为什么不能x[0]呢?非常感谢你!
JZAU

1
@Boern d.items()返回一个类似列表的(key, value)元组容器。[0]访问元组的第一个元素-键-并[1]访问第二个元素-值。
BallpointBen

2
注:由于3.6(作为CPython的/ PyPy的实现细节)和3.7(以Python语言担保),纯dict是插入排序为好,这样只需更换OrderedDictdict代码现代Python的运行。OrderedDict除非您需要重新排列现有顺序dict(使用move_to_end/ popitem)或需要相等比较以使顺序敏感,否则不再需要它了。它比plain占用更多的内存dict,因此,如果可以的话,这dict是可行的方法。
ShadowRanger

104

更新:2015年12月5日使用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)])

86

Hank Gay的答案几乎相同:

sorted([(value,key) for (key,value) in mydict.items()])

或根据John Fouhy的建议进行了稍微优化:

sorted((value,key) for (key,value) in mydict.items())

9
..和汉克·盖伊的答案一样,您不需要方括号。sorted()将很高兴采用任何可迭代的方法,例如生成器表达式。
John Fouhy

您可能仍然需要交换(value,key)元组元素,以(key,value)结尾。然后需要另一个列表理解。 [(key, value) for (value, key) in sorted_list_of_tuples]
saidimu apale

不,最好sorted放在方括号中,因为无论如何都必须重建列表,并且从gencomp重建会更快。对代码高尔夫有利,对速度不利。保持丑陋的([])版本。
让弗朗索瓦法布尔

75

使用namedtuple通常很方便。例如,您有一个“名称”作为键,而“分数”作为值的字典,并且您想对“分数”进行排序:

import collections
Player = collections.namedtuple('Player', 'score name')
d = {'John':5, 'Alex':10, 'Richard': 7}

首先以最低分数排序:

worst = sorted(Player(v,k) for (k,v) in d.items())

首先以最高分排序:

best = sorted([Player(v,k) for (k,v) in d.items()], reverse=True)

现在您可以得到Python的第二好玩家(index = 1)的名称和得分,如下所示:

player = best[1]
player.name
    'Richard'
player.score
    7

如何将其转换回字典?
rowana

as_list = [d.items()中(k,v)的播放器(v,k)] as_dict = dict(as_list中p的(p.name,p.score))
Remi

72

Python 3.6开始,将对内置字典进行排序

好消息,因此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+内置字典!):

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 3.6 dict的 python-dev的邮件”中宣布紧凑并获得私有版本;由于在Python 3.6中已解决/实现了问题27350 “紧凑且有序的字典”,因此关键字变得有序”,我们现在可以使用内置的字典来维护插入顺序!!

希望这将导致第一步的薄层OrderedDict实现。就像@ JimFasarakis-Hilliard指出的那样,将来还会看到一些OrderedDict类型的用例。我认为整个Python社区都会仔细检查,是否经得起时间的考验以及下一步将是什么。

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

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

第一个是因为它在某些情况下简化了函数和方法的实现中的分派。

第二个参数鼓励使用dicts作为处理管道中的中间存储。

Raymond Hettinger 从旧金山Python Meetup Group的演讲2016-DEC-08中提供了解释“ Python 3.6词典背后的技术文档。

也许相当一部分Stack Overflow高修饰度的问答页面会收到此信息的变体,并且许多高质量的答案也需要按版本进行更新。

警告购买者(另请参阅下面的2017年12月15日更新):

正如@ajcr正确指出的那样:“此新实现的顺序保留方面被认为是实现细节,因此不应依赖。” (摘自whatsnew36)并不是很挑剔,引文有点悲观了;-)。它继续显示为“(将来可能会改变,但是希望在更改语言规范以强制所有当前和将来的Python实现保留顺序语义之前,先在几个版本中使用该语言的新dict实现;有助于保持与仍旧有效的随机迭代顺序的旧版语言(例如Python 3.5)的向后兼容性。”

因此,就像在某些人类语言(例如德语)中一样,用法决定了语言的使用方式,现在遗嘱已在whatsnew36中声明。

更新2017-12-15:

发给python-dev列表邮件中,Guido van Rossum声明:

做到这一点。裁定“裁定保留插入顺序”。谢谢!

因此,dict插入顺序的3.6 CPython版本的副作用现在已成为语言规范的一部分(并且不再仅仅是实现细节)。collections.OrderedDict正如雷蒙德·海廷格(Raymond Hettinger)在讨论中所提醒的那样,该邮件线程还浮出了一些与众不同的设计目标。


15
您要链接到“新消息”页面上的警告应予以强调:此新实现的顺序保留方面被认为是实现细节,不应依赖。没有人应该假定该dict类型将遵守其代码中的插入顺序。这不是语言定义的一部分,实现可能会在将来的任何发行版中更改。继续使用OrderedDict以保证订单。
Alex Riley

@ajcr感谢您的警告,非常感谢-笑脸和我的回答中可能包含了笑脸,这些应该表明,变化很大,但是当然仅适用于CPython(参考实现)和PyPy。对于完全不同的东西……在编写人机指令时,我很少谈论未实现的细节。如果只是Jython ;-) ...我可能没有勇气编写它。
Dilettant

OrderedDict绝对不会被丢弃;取而代之的是,它将成为当前dict实现周围的薄薄包装(因此您可能会补充说,它也将变得更加紧凑)。将该代码段添加进来ImportError并不是最好的主意,因为它会误导OrderedDict没有用的读者。
Dimitris Fasarakis Hilliard,2016年

@ JimFasarakis-Hilliard感谢您的反馈。“最好的主意”让我微笑-未来往往很难预测。但我喜欢您的建议,请检查来源,尝试一下,然后相应地更新答案。再次感谢。
Dilettant

8
@AlexRiley此警告不再准确。Python3.7保证有序字典。
Gerrit

42

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

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

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

请注意,顺序定义不正确(具有相同值的键在输出列表中将以任意顺序排列)。


1
您缺少结果的值
Dejell 2014年

请注意,您既要迭代字典,又要按其键取值,所以从性能角度来看,这不是最佳解决方案。
罗恩·克莱因

1
@Dejell:正如贡献者所说,他将问题解释为“我能否获得根据值排序的键列表”。我们不需要结果中的值,我们将它们存储在字典中。
最多

36

如果值是数字,则也可以Countercollections中使用。

from collections import Counter

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

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

如果字典是>>> x = {'hello':1,'python':5,'world':300}
怎么办?

@yopy Counter({'hello':1, 'python':5, 'world':300}).most_common()[('world', 300), ('python', 5), ('hello', 1)]。这实际上适用于任何可排序的值类型(尽管许多其他 Counter操作确实要求值与int相当)。
lvc

34

在Python 2.7中,只需执行以下操作:

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

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

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

复制粘贴自:http : //docs.python.org/dev/library/collections.html#ordereddict-examples-and-recipes

请享用 ;-)


25

这是代码:

import operator
origin_list = [
    {"name": "foo", "rank": 0, "rofl": 20000},
    {"name": "Silly", "rank": 15, "rofl": 1000},
    {"name": "Baa", "rank": 300, "rofl": 20},
    {"name": "Zoo", "rank": 10, "rofl": 200},
    {"name": "Penguin", "rank": -1, "rofl": 10000}
]
print ">> Original >>"
for foo in origin_list:
    print foo

print "\n>> Rofl sort >>"
for foo in sorted(origin_list, key=operator.itemgetter("rofl")):
    print foo

print "\n>> Rank sort >>"
for foo in sorted(origin_list, key=operator.itemgetter("rank")):
    print foo

结果如下:

原版的

{'name': 'foo', 'rank': 0, 'rofl': 20000}
{'name': 'Silly', 'rank': 15, 'rofl': 1000}
{'name': 'Baa', 'rank': 300, 'rofl': 20}
{'name': 'Zoo', 'rank': 10, 'rofl': 200}
{'name': 'Penguin', 'rank': -1, 'rofl': 10000}

罗夫

{'name': 'Baa', 'rank': 300, 'rofl': 20}
{'name': 'Zoo', 'rank': 10, 'rofl': 200}
{'name': 'Silly', 'rank': 15, 'rofl': 1000}
{'name': 'Penguin', 'rank': -1, 'rofl': 10000}
{'name': 'foo', 'rank': 0, 'rofl': 20000}

{'name': 'Penguin', 'rank': -1, 'rofl': 10000}
{'name': 'foo', 'rank': 0, 'rofl': 20000}
{'name': 'Zoo', 'rank': 10, 'rofl': 200}
{'name': 'Silly', 'rank': 15, 'rofl': 1000}
{'name': 'Baa', 'rank': 300, 'rofl': 20}

25

请尝试以下方法。让我们用以下数据定义一个名为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

太棒了!for key, value in sorted(mydict.iteritems(), key=lambda (k,v): v["score"]):允许您按子项排序
Andomar '17

它使我在Python3中的lambda附近出现语法错误
Suleman Elahi

21

从Python 3.6开始,dict对象现在按插入顺序排序。它正式在Python 3.7的规范中。

>>> words = {"python": 2, "blah": 4, "alice": 3}
>>> dict(sorted(words.items(), key=lambda x: x[1]))
{'python': 2, 'alice': 3, 'blah': 4}

在此之前,您必须使用OrderedDict

Python 3.7文档说:

在版本3.7中更改:保证字典顺序为插入顺序。此行为是3.6版CPython的实现细节。


很棒!dict(sorted(words.items(), key=lambda x: x[1], reverse=True))对于DESC
vizyourdata '18

20

您可以创建一个“倒排索引”

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]

19

您可以使用collections.Counter。请注意,这对于数字和非数字值均适用。

>>> x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
>>> from collections import Counter
>>> #To sort in reverse order
>>> Counter(x).most_common()
[(3, 4), (4, 3), (1, 2), (2, 1), (0, 0)]
>>> #To sort in ascending order
>>> Counter(x).most_common()[::-1]
[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]
>>> #To get a dictionary sorted by values
>>> from collections import OrderedDict
>>> OrderedDict(Counter(x).most_common()[::-1])
OrderedDict([(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)])

7
这与Ivan Sas的答案有何不同?
Peter Mortensen

15

您可以使用skip dict,这是一个按值永久排序的字典。

>>> data = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
>>> SkipDict(data)
{0: 0.0, 2: 1.0, 1: 2.0, 4: 3.0, 3: 4.0}

如果使用keys()values()或者items()那么你会在排序顺序通过值迭代。

它是使用跳过列表数据结构实现的。


我们可以更改排序顺序吗,现在是升序,但是我想降序。
Suleman Elahi

afaik,您将不得不
取舍

哇,我不这么想...谢谢。
Suleman Elahi


12
from django.utils.datastructures import SortedDict

def sortedDictByKey(self,data):
    """Sorted dictionary order by key"""
    sortedDict = SortedDict()
    if data:
        if isinstance(data, dict):
            sortedKey = sorted(data.keys())
            for k in sortedKey:
                sortedDict[k] = data[k]
    return sortedDict

2
问题是:按值排序,而不是按键排序...我喜欢看函数。您可以导入集合,当然也可以使用sorted(data.values())
Remi,

10

正如Dilettant指出的那样,Python 3.6现在将保持顺序!我以为我会分享我编写的一个函数,该函数可以简化可迭代对象(元组,列表,字典)的排序。在后一种情况下,您可以对键或值进行排序,并且可以考虑数字比较。仅适用于> = 3.6!

当您尝试在包含字符串和整数的可迭代对象上使用sorted时,sorted()将失败。当然,您可以使用str()强制进行字符串比较。但是,在某些情况下,您想进行小于的实际数字比较(在字符串比较中不是这种情况)。因此,我提出了以下建议。当您需要显式数值比较时,可以使用该标志,该标志将尝试通过将所有值都转换为浮点数来进行显式数值排序。如果成功,它将进行数字排序,否则将使用字符串比较。1220num_as_num

欢迎提出改进或推送要求的评论。

def sort_iterable(iterable, sort_on=None, reverse=False, num_as_num=False):
    def _sort(i):
      # sort by 0 = keys, 1 values, None for lists and tuples
      try:
        if num_as_num:
          if i is None:
            _sorted = sorted(iterable, key=lambda v: float(v), reverse=reverse)
          else:
            _sorted = dict(sorted(iterable.items(), key=lambda v: float(v[i]), reverse=reverse))
        else:
          raise TypeError
      except (TypeError, ValueError):
        if i is None:
          _sorted = sorted(iterable, key=lambda v: str(v), reverse=reverse)
        else:
          _sorted = dict(sorted(iterable.items(), key=lambda v: str(v[i]), reverse=reverse))

      return _sorted

    if isinstance(iterable, list):
      sorted_list = _sort(None)
      return sorted_list
    elif isinstance(iterable, tuple):
      sorted_list = tuple(_sort(None))
      return sorted_list
    elif isinstance(iterable, dict):
      if sort_on == 'keys':
        sorted_dict = _sort(0)
        return sorted_dict
      elif sort_on == 'values':
        sorted_dict = _sort(1)
        return sorted_dict
      elif sort_on is not None:
        raise ValueError(f"Unexpected value {sort_on} for sort_on. When sorting a dict, use key or values")
    else:
      raise TypeError(f"Unexpected type {type(iterable)} for iterable. Expected a list, tuple, or dict")

9

这是在d.values()d.keys()上使用zip的解决方案。该链接(在Dictionary视图对象上)下面的几行是:

这允许使用zip()创建(值,键)对:pair = zip(d.values(),d.keys())。

因此,我们可以执行以下操作:

d = {'key1': 874.7, 'key2': 5, 'key3': 8.1}

d_sorted = sorted(zip(d.values(), d.keys()))

print d_sorted 
# prints: [(5, 'key2'), (8.1, 'key3'), (874.7, 'key1')]

9

当然,请记住,您需要使用它,OrderedDict因为常规Python字典不会保留原始顺序。

from collections import OrderedDict
a = OrderedDict(sorted(originalDict.items(), key=lambda x: x[1]))

如果您没有Python 2.7或更高版本,则最好的办法是迭代生成器函数中的值。(有一个OrderedDict2.4和2.6 在这里,但

a)我不知道它的效果如何

b)当然,您必须下载并安装它。如果您没有管理权限,那么恐怕该选项不可用了。)


def gen(originalDict):
    for x, y in sorted(zip(originalDict.keys(), originalDict.values()), key=lambda z: z[1]):
        yield (x, y)
    #Yields as a tuple with (key, value). You can iterate with conditional clauses to get what you want. 

for bleh, meh in gen(myDict):
    if bleh == "foo":
        print(myDict[bleh])

您还可以打印出每个值

for bleh, meh in gen(myDict):
    print(bleh, meh)

如果未使用Python 3.0或更高版本,请记住在打印后删除括号


常规Python字典不会保留原始顺序 -从Python 3.7开始,它们会保留原始顺序
Gerrit


6

这适用于3.1.x:

import operator
slovar_sorted=sorted(slovar.items(), key=operator.itemgetter(1), reverse=True)
print(slovar_sorted)

6

刚刚从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))

样本输出:

#Asending 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')]

这是按键排序,而不是按值排序。
Rubel

如果要以初始格式打印,则应执行以下操作:print([sorted中的[,v,k是[[(k,v),d.items()中的k,v是[[v,k)]]]))。输出为:[['orange',1.0),('apple',500.1),('pineapple',789.0),('banana',1500.2)]。对于[(k,v)表示已排序的v,k([(v,k)表示d.items()中的k,v,reverse = True)],输出为:[('banana',1500.2), ('菠萝',789.0),('苹果',500.1),('橙色',1.0)]
Hermes Morales

5

遍历字典并按其值降序对其进行排序:

$ python --version
Python 3.2.2

$ cat sort_dict_by_val_desc.py 
dictionary = dict(siis = 1, sana = 2, joka = 3, tuli = 4, aina = 5)
for word in sorted(dictionary, key=dictionary.get, reverse=True):
  print(word, dictionary[word])

$ python sort_dict_by_val_desc.py 
aina 5
tuli 4
joka 3
sana 2
siis 1


5

为了完整起见,我发布了一个使用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)]

4

由于需要保持与旧版本Python的向后兼容性,我认为OrderedDict解决方案非常不明智。您需要适用于Python 2.7和更早版本的工具。

但是,另一个答案中提到的集合解决方案绝对是极好的,因为您可以重新训练键和值之间的联系,这对于字典而言极为重要。

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

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

from collections import Counter

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


>> [('python', 5), ('world', 3), ('hello', 1)]
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.