我有一个从数据库中的两个字段中读取值的字典:一个字符串字段和一个数字字段。字符串字段是唯一的,所以这是字典的关键。
我可以对键进行排序,但是如何根据这些值进行排序?
注意:我已阅读Stack Overflow问题
答案
无法对字典进行排序,只能得到已排序的字典的表示形式。字典本质上是无序的,但其他类型,如列表和元组,不是。所以你需要一个有序的数据类型来表示排序的值,这将是一个列表 – 可能是一个元组列表。
例如,
importoperator
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。
对于那些希望按键而不是数值进行排序的人:
importoperator
x= {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}sorted_x=sorted(x.items(),key=operator.itemgetter(0))
简单如下: sorted(dict1, key=dict1.get)
那么,它实际上可以做一个“按字典值排序”。最近我不得不在Code Golf中做这件事(Stack Overflow question
如果您构造一个字典,其中的关键词和每个词的出现次数为值,在此简化为:
fromcollectionsimportdefaultdict
d=defaultdict(int)
forwintext.split():d[w] += 1
那么你可以得到一个单词列表,按使用频率sorted(d, key=d.get)排序 – 排序迭代字典键,使用单词出现次数作为排序键。
forwinsorted(d,key=d.get,reverse=True):
printw,d[w]
我正在写这个详细的解释来说明人们通常所说的“我可以轻松地按键排序字典,但我怎么按价值排序” – 我认为OP正试图解决这个问题。解决方案是根据数值对键进行排序,如上所示。
你可以使用:
sorted(d.items(), key=lambda x: x[1])
这将按字典中的每个条目从最小到最大的值对字典进行排序。
字典不能排序,但你可以从它们建立一个排序列表。
字典值的排序列表:
sorted(d.values())
(键,值)对的列表,按值排序:
fromoperatorimportitemgetter
sorted(d.items(),key=itemgetter(1))
在最近的Python 2.7中,我们有了新的OrderedDict类型,它记住了添加项目的顺序。
>>>d= {"third": 3, "first": 1, "fourth": 4, "second": 2}
>>> fork,vind.items():
... print "%s: %s" % (k,v)
...second: 2fourth: 4third: 3first: 1
>>>d{'second': 2, 'fourth': 4, 'third': 3, 'first': 1}
要从原始中创建一个新的有序字典,按值排序:
>>> fromcollectionsimport OrderedDict
>>>d_sorted_by_value= OrderedDict(sorted(d.items(),key=lambdax:x[1]))
OrderedDict的行为像一个正常的字典:
>>> fork,vind_sorted_by_value.items():
... print "%s: %s" % (k,v)
...first: 1second: 2third: 3fourth: 4
>>>d_sorted_by_valueOrderedDict([('first': 1), ('second': 2), ('third': 3), ('fourth': 4)])
更新:2015年12月5日使用Python 3.5
虽然我发现接受的答案很有用,但我还惊讶于它没有更新为从标准库集合模块中引用
fromoperatorimportitemgetterfromcollectionsimport OrderedDictx= {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)])
官方
# regular unsorted dictionaryd= {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}
# dictionary sorted by value
OrderedDict(sorted(d.items(),key=lambdat:t[1]))
# OrderedDict([('pear', 1), ('orange', 2), ('banana', 3), ('apple', 4)])
使用
importcollectionsPlayer =collections.namedtuple('Player', 'score name')d= {'John':5, 'Alex':10, 'Richard': 7}
先以最低分数排序:
worst=sorted(Player(v,k) for (k,v) ind.items())
以最高得分排序:
best=sorted([Player(v,k) for (k,v) ind.items()],reverse=True)
现在你可以得到它的名字和得分,比如说,我们说第二好的球员(index = 1)非常像Python:
player=best[1]player.name'Richard'player.score7
从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))
稍后允许输出为:
fork,vinordered_map.items():
print(k,v)
在这种情况下产生(对于新的Python 3.6 +内置字典!):
foo0bar1baz42
按每个v值的顺序排列。
在我的机器上安装Python 3.5的地方,它现在会产生:
bar1foo0baz42
细节:
正如Raymond Hettinger在2012年提出的(参见python-dev主题为“更紧凑的词典,更快的迭代”),现在(2016年),Victor Stinner在Python-dev的邮件中宣布了Python的Python 3.6 dict变为压缩并获得一个私有版本;而且由于Python 3.6中的问题27350的修复/实现“紧凑且有序的dict”,我们现在可以使用内置的字典来维护插入顺序,因此关键字变得有序!
希望这将导致OrderedDict实现的薄层作为第一步。正如@ JimFasarakis-Hilliard所指出的那样,有些人在将来也会看到OrderedDict类型的用例。我认为,如果这将经得起时间的考验,接下来的步骤是什么,那么Python社区将会仔细检查。
现在是时候重新思考我们的编码习惯,不要错过稳定排序开放的可能性:
关键字参数和
(中级)dict存储
第一个是因为它在某些情况下简化了函数和方法的实现。
第二,它鼓励更容易地使用dicts作为处理管道中的中间存储。
Raymond Hettinger亲切地提供了解释“ The Python Behind Python 3.6 Dictionaries ”的文档- 来自他的旧金山Python Meetup Group发布的2016-DEC-08。
也许一些Stack Overflow高级问答页面会收到这些信息的变体,许多高质量的答案也需要每个版本的更新。
警惕Emptor(但也见下文更新2017-12-15):
正如@ajcr正确地指出:“这个新实现的顺序保留方面被认为是一个实现细节,不应该依赖。” (来自whatsnew36)没有挑选,但引用被削减了一点悲观;-)。它继续为“(这可能会在未来发生变化,但希望在将语言规范更改为强制顺序保留语义之前,在少数版本中使用该语言实现此新的dict;这也是所有当前和未来Python实现的保留语义有助于保持与旧版本语言的向后兼容性,即随机迭代顺序仍然有效,例如Python 3.5)。“
正如在一些人类语言(例如德语)中那样,用法形成了语言,意志现在已经被宣布……在whatsnew36中。
2017-12-15更新:
在发给python-dev名单的邮件中,Guido van Rossum宣称:
做到这一点。“Dict保持插入顺序”是裁决。谢谢!
因此,dict插入排序的3.6版CPython副作用现在已成为语言规范的一部分(而不仅仅是一个实现细节)。collections.OrderedDict正如Raymond Hettinger在讨论中提醒的那样,该邮件线程还提供了一些可区分的设计目标。
我遇到了同样的问题,我解决了这个问题:
WantedOutput =sorted(MyDict,key=lambdax: MyDict[x])
(回答“不可能排序字典”的人没有读到这个问题!事实上,“我可以对键进行排序,但是我怎样才能根据这些值进行排序?”显然意味着他想要一个列表按照它们的值的值排序的键)。
请注意订单没有被很好地定义(在输出列表中,具有相同值的键将以任意顺序)。
这是代码:
importoperator
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 >>"
forfooinorigin_list:
printfooprint "\n>> Rofl sort >>"
forfooinsorted(origin_list,key=operator.itemgetter("rofl")):
printfooprint "\n>> Rank sort >>"
forfooinsorted(origin_list,key=operator.itemgetter("rank")):
printfoo
结果如下:
原版的
{'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}
ROFL
{'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}