ChatGPT解决这个技术问题 Extra ChatGPT

如何按值对字典进行排序?

这个问题的答案是社区的努力。编辑现有答案以改进这篇文章。它目前不接受新的答案或交互。

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

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

注意:我在这里阅读了 Stack Overflow 问题 How do I sort a list of dictionaries by a value of the dictionary? 并且可能可以将我的代码更改为有一个字典列表,但是由于我真的不需要字典列表,所以我想知道是否有按升序或降序排序的更简单的解决方案。

字典数据结构没有内在的顺序。您可以迭代它,但没有什么可以保证迭代将遵循任何特定的顺序。这是设计使然,因此您最好的选择可能是使用另一种数据结构进行表示。
“sorted()”可以对字典进行操作(并返回排序键列表),所以我认为他知道这一点。在不了解他的程序的情况下,告诉别人他们使用了错误的数据结构是荒谬的。如果 90% 的时间都需要快速查找,那么 dict 可能就是你想要的。
此处以简洁明了的方式介绍了排序字典的所有三个输出(键、值,两者):stackoverflow.com/questions/16772071/sort-dict-by-value-python
@Daishiman 基类可能没有被订购,但 OrderedDict 当然是。
在 Python 3.6+ 字典中保留插入顺序。当然,这与按值排序的可能性不同,但另一方面,说“字典数据结构没有固有顺序”不再有效。

w
wjandrea

Python 3.7+ 或 CPython 3.6

字典在 Python 3.7+ 中保留插入顺序。在 CPython 3.6 中相同,但 it's an implementation detail

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

或者

>>> 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 中,因为 unpacking is not allowed 我们可以使用

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

如果您希望输出为 dict,您可以使用 collections.OrderedDict

import collections

sorted_dict = collections.OrderedDict(sorted_x)

对于按值方案排序的各种字典的时间安排:writeonly.wordpress.com/2008/08/30/…
sorted_x.reverse() 将为您提供降序(按第二个元组元素)
saidimu:由于我们已经在使用 sorted(),因此传入 reverse=True 参数会更有效。
在 python3 中,我使用了 lambda:sorted(d.items(), key=lambda x: x[1])。这会在 python 2.x 中工作吗?
请问在哪里可以阅读有关 key=lambda item :item[1] 用法的更多信息?我不太明白的部分是item[1],是不是因为当我们执行x.items()时它会返回键值对,这样我们就可以通过执行item[1]来获取值?
B
Boris Verkhovskiy

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

好吧,实际上可以进行“按字典值排序”。最近我不得不在 Code Golf 中这样做(堆栈溢出问题 Code golf: Word frequency chart)。简而言之,问题是这样的:给定一个文本,计算每个单词出现的频率,并显示一个排名靠前的单词列表,按频率递减排序。

如果你构建一个以单词为键,每个单词出现的次数为值的字典,这里简化为:

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

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


这也很好,但 key=operator.itemgetter(1) 应该比 key=d.get 更具可扩展性
@bli sorted_keys = sorted(d.items(), key=itemgetter(1), reverse=True)for key, val in sorted_keys: print "%s: %d" % (key, val) - itemgetter 在调用时会创建一个函数,您不会像在示例中那样直接使用它。对 dict 的简单迭代使用没有值的键
我从未来来告诉你 collections.Counter,它有一个你可能感兴趣的 most_common 方法 :)
S
Suresh2692

你可以使用:

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
我个人更喜欢key=lambda (k, v): v
@Keyo 不应该返回键的有序列表(按值排序)而不是 (k,v) 元组吗?这就是我在 Python 2.7.10 中得到的。 @Nyxynyx 添加参数 reverse=True 以降序排序。
@Claudiu 我也喜欢这种 (k, v) 语法,但它在删除 tuple parameter unpacking 的 Python 3 中不可用。
如果将其包装在 OrderedDict() 实例中,您将获得(有序)字典而不是元组列表!
R
Roberto Bonvallet

无法对字典进行排序,但您可以从中构建排序列表。

dict 值的排序列表:

sorted(d.values())

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

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

具有相同值的键按什么顺序放置?我首先按键对列表进行排序,然后按值对列表进行排序,但是具有相同值的键的顺序不会保留。
现在可以对字典进行排序,从 CPython 3.6 开始,所有其他 Python 实现从 3.7 开始
当时确实如此,但现在 python 字典默认保留了已插入项目的顺序。因此可以对它们进行排序。
P
Peter Mortensen

在最近的 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 的行为类似于普通的 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)])

这不是问题所在 - 这不是关于维护键的顺序,而是关于“按值排序”
@Nas Banov:它不是按密钥排序的。它按顺序排序,我们创建项目。在我们的例子中,我们按值排序。不幸的是,不幸地选择了 3 项 dict,所以当按值和键对 voth 进行排序时,顺序是相同的,所以我扩展了示例 dict。
sorted(d.items(), key=lambda x: x[1]) 您能解释一下 x 的含义吗,为什么它可以将 x[1] 转换为 lambda?为什么不能是x[0]?非常感谢!
@Boern d.items() 返回 (key, value) 元组的类似列表的容器。 [0] 访问元组的第一个元素 - 键 - 而 [1] 访问第二个元素 - 值。
注意:从 3.6 开始(作为 CPython/PyPy 实现细节)和从 3.7 开始(作为 Python 语言保证),纯 dict 也是插入顺序的,因此您可以将 OrderedDict 替换为 dict 代码在现代 Python 上运行。除非您需要重新排列现有 dict 的顺序(使用 move_to_end/popitem)或需要相等比较来区分顺序,否则实际上不再需要 OrderedDict。它比普通的 dict 使用更多的内存,所以如果可以的话,dict 是要走的路。
a
arcseldon

更新:2015 年 12 月 5 日使用 Python 3.5

虽然我发现接受的答案很有用,但令我感到惊讶的是,它没有被更新以引用标准库 collections 模块中的 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)])

你能解释一下 itemgetter 在这个例子中做了什么吗?否则这看起来就像使用兰巴一样神秘
J
Justin Batch

Hank Gay's answer 几乎相同:

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

或者按照 John Fouhy 的建议进行轻微优化:

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

..和汉克盖伊的回答一样,你不需要方括号。 sorted() 将愉快地接受任何可迭代的,例如生成器表达式。
您可能仍需要交换 (value,key) 元组元素以最终得到 (key, value)。然后需要另一个列表理解。 [(key, value) for (value, key) in sorted_list_of_tuples]
不,最好保留方括号,因为 sorted 无论如何都必须重建列表,并且从 gencomp 重建会更快。对代码高尔夫有好处,对速度不利。保留丑陋的 ([]) 版本。
我很困惑,这会返回一个元组数组而不是字典。 IMO 您缺少听写理解部分:{x: v for x, v in sorted((value, key) for (key, value) in mydict.items())}
D
Dilettant

从 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+ 内置字典!):

foo 0
bar 1
baz 42

每个 v 值的顺序相同。

在我的机器上安装 Python 3.5 时,它目前产生:

bar 1
foo 0
baz 42

细节:

正如 Raymond Hettinger 于 2012 年提出的(参见主题为 "More compact dictionaries with faster iteration" 的 python-dev 上的邮件)和现在(2016 年)由 Victor Stinner 在主题为 "Python 3.6 dict becomes compact and gets a private version; and keywords become ordered" 的邮件中宣布,由于修复/实施在 Python 3.6 中的 issue 27350 "Compact and ordered dict" 我们现在可以使用内置的 dict 来维护插入顺序!!

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

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

关键字参数和

(中级)字典存储

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

第二个,因为它鼓励更轻松地将 dict 用作处理管道中的中间存储。

Raymond Hettinger 提供了解释“The Tech Behind Python 3.6 Dictionaries”的文档 - 来自他的旧金山 Python Meetup Group 演示文稿 2016-DEC-08。

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

Caveat Emptor(但另见下文更新 2017-12-15):

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

因此,在某些人类语言(例如德语)中,用法塑造了语言,并且现在已经在 whatsnew36 中声明了遗嘱。

2017 年 12 月 15 日更新:

mail to the python-dev list 中,Guido van Rossum 宣称:

让它如此。 “字典保持插入顺序”是裁决。谢谢!

因此,dict 插入排序的 3.6 版 CPython 副作用现在成为语言规范的一部分(不再只是实现细节)。正如 Raymond Hettinger 在讨论中提醒的那样,该邮件主题还提出了 collections.OrderedDict 的一些显着设计目标。


@ajcr 感谢您的警告,非常感谢 - 因为笑脸和也许的被编织到我的回复中,这些应该表明,变化是巨大的,但当然,仅适用于 CPython(参考实现)和 PyPy。对于完全不同的东西......我在编写人机指令时很少谈论非实现细节。如果它只是 Jython ;-) ...我可能没有勇气写它。
OrderedDict 绝对不会被丢弃;相反,它将成为当前 dict 实现的薄包装器(因此您可能会补充说它也会变得更加紧凑)。使用 ImportError 添加该片段并不是最好的主意,因为它会误导读者认为 OrderedDict 没有用处。
作为对此答案和结构化字典的回应,我发布了 a new answer。欢迎反馈!
v
vallentin

使用 namedtuple 通常非常方便。例如,你有一个字典,'name' 作为键,'score' 作为值,你想按'score' 排序:

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 方式获得第二好的玩家(索引=1)的名称和分数:

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

我怎样才能将它转换回字典?
as_list=[Player(v,k) for (k,v) in d.items()] as_dict=dict((p.name,p.score) for p in as_list)
P
Peter Mortensen

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

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

(回答“It is not possible to sort a dict”的人没有读过这个问题!事实上,“我可以按键排序,但是如何根据值排序?”显然意味着他想要一个列表键根据其值的值排序。)

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


请注意,您既要迭代字典,又要按其键获取值,因此在性能方面,这不是最佳解决方案。
@Dejell:正如贡献者所说,他将问题解释为“我可以获得根据值排序的键列表”。我们不需要结果中的值,我们在字典中有它们。
G
Georgy

如果值是数字,您也可以使用 collections 中的 Counter

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)]。这实际上适用于任何可排序的值类型(尽管许多 other 计数器操作确实需要值与整数相当)。
s
sweetdream

在 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

享受 ;-)


i
icedwater

这是代码:

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}

P
Peter Mortensen

尝试以下方法。让我们用以下数据定义一个名为 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"]): 允许您按子键排序
这在不支持元组解包并且字典不再具有 iteritems() 的更高版本的 python 中不起作用
M
Maxime Chéramy

从 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 documentation 说:

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


效果很好! dict(sorted(words.items(), key=lambda x: x[1], reverse=True)) 用于 DESC
S
S.Lott

您也可以创建“倒排索引”

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]

P
Peter Mortensen

您可以使用 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)])

这与 Ivan Sas's answer 有何不同?
m
malthe

您可以使用 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(),那么您将按值按排序顺序进行迭代。

它是使用 skip list 数据结构实现的。


我们可以更改排序顺序吗?现在,它正在上升,但我想要下降。
afaik 你必须否定你的价值观才能颠倒顺序
G
Georgy

您还可以使用可以传递给 key 的自定义函数。

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

这是迄今为止在 python 2.7 中唯一有效的答案
G
Georgy

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

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

如果您没有 Python 2.7 或更高版本,那么您能做的最好的事情就是迭代生成器函数中的值。 (对于 2.4 和 2.6 here,有一个 OrderedDict,但是

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 开始,它们保持不变。
E
Eamonn Kenny

另一个答案中提到的集合解决方案绝对是一流的,因为您保留了键和值之间的联系,这在字典的情况下非常重要。

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

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

from collections import Counter

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


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

A
Argun
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

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

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

这允许使用 zip() 创建(值,键)对:pairs = 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')]

B
Bram Vanroy

As pointed out by Dilettant,Python 3.6 现在将保持顺序!我想我会分享一个我编写的函数,它可以简化可迭代(元组、列表、字典)的排序。在后一种情况下,您可以按键或值进行排序,并且可以考虑数字比较。 仅适用于 >= 3.6!

当您尝试在包含字符串和整数的可迭代对象上使用 sorted 时,sorted() 将失败。当然,您可以强制使用 str() 进行字符串比较。但是,在某些情况下,您希望在 12 小于 20 的情况下进行 actual 数值比较(字符串比较中并非如此)。所以我想出了以下内容。当您想要显式数字比较时,您可以使用标志 num_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")

m
mcgag

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

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

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

如果你想以初始格式打印它,你应该这样做:print ([(k,v) for v,k in sorted([(v,k) for k,v in d.items()])]) 。输出为:[('orange', 1.0), ('apple', 500.1), ('pineapple', 789.0), ('banana', 1500.2)]。使用 [(k,v) for v,k in sorted([(v,k) for k,v in d.items()], reverse = True)] 输出为: [('banana', 1500.2), ('菠萝', 789.0), ('苹果', 500.1), ('橙子', 1.0)]
p
ponty

使用 dicts 中的 ValueSortedDict

from dicts.sorteddict import ValueSortedDict
d = {1: 2, 3: 4, 4:3, 2:1, 0:0}
sorted_dict = ValueSortedDict(d)
print sorted_dict.items() 

[(0, 0), (2, 1), (1, 2), (4, 3), (3, 4)]

j
juhoh

遍历 dict 并按其值降序排序:

$ 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

P
Petr Viktorin

如果您的值是整数,并且您使用 Python 2.7 或更高版本,则可以使用 collections.Counter 而不是 dictmost_common 方法将为您提供按值排序的所有项目。


N
Nathaniel Ford

这适用于 3.1.x:

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

A
Abhijit

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