sort - python有序字典




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

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年提出的那样(参见python-dev上的邮件主题为“更紧凑的词典和更快速的迭代” ),现在(2016年)由Victor Stinner在邮件中宣布python-dev主题为“Python 3.6 dict”紧凑并获得私有版本;关键字变得有序“由于问题27350的修复/实现”紧凑和有序的dict“在Python 3.6中我们现在可以使用内置的dict来维护插入顺序!!

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

是时候重新考虑我们的编码习惯,不要错过稳定订购的可能性:

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

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

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

Raymond Hettinger在他的旧金山Python Meetup Group演讲2016-DEC-08上提供了解释“ Python 3.6 Dictionaries背后的技术文档。

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

警告Empat(但也见下面更新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在提及讨论时提到了订单。

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

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

注意:我已阅读Stack Overflow问题如何按Python中字典的值对字典列表进行排序? 并且可能会改变我的代码以获得字典列表,但由于我不需要字典列表,我想知道是否有更简单的解决方案。


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

嗯,实际上可以做一个“按字典值排序”。 最近我必须在Code Golf(问题代码高尔夫:Word频率图表 )中这样做。 简而言之,问题就是这样:给定一个文本,计算每个单词遇到的频率,并显示顶部单词列表,按频率降低排序。

如果构造一个字典,其中单词为键,每个单词的出现次数为值,则简化为:

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

然后你可以得到一个单词列表,按使用频率sorted(d, key=d.get)sorted(d, key=d.get) - 排序迭代字典键,使用单词出现次数作为排序键。

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

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


更新: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作为sort函数:

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

不可能对字典进行排序,只是为了获得已排序的字典的表示。 字典本质上是无序的,但其他类型(如列表和元组)则不是。 因此,您需要一个有序数据类型来表示排序值,这将是一个列表 - 可能是元组列表。

例如,

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_by_value = sorted(x.items(), key=lambda kv: kv[1])

从技术上讲,字典不是序列,因此无法排序。 你可以做点什么

sorted(a_dictionary.values())

假设表现不是很大。


你可以使用:

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

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


使用来自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)]

在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-recipeshttp://docs.python.org/dev/library/collections.html#ordereddict-examples-and-recipes

请享用 ;-)


如果值是数字,您还可以使用集合中的计数器

from collections import Counter

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


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

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


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

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

如果您没有Python 2.7或更高版本,那么您可以做的最好是迭代生成器函数中的值。 (这里有2.4和2.6的OrderedDict,但是

a) I don't know about how well it works 

b) You have to download and install it of course. If you do not have administrative access, then I'm afraid the option's out.)
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或更高版本,请记得在打印后删除括号


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

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]

您可以使用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()那么您将按值排序。

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



我想出了这个,

import operator    
x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
sorted_x = {k[0]:k[1] for k in sorted(x.items(), key=operator.itemgetter(1))}

对于Python 3.x: x.items()替换iteritems()

>>> sorted_x
{0: 0, 1: 2, 2: 1, 3: 4, 4: 3}

或尝试使用collections.OrderedDict

x = {1: 2, 3: 4, 4:3, 2:1, 0:0}
from collections import OrderedDict

od1 = OrderedDict(sorted(x.items(), key=lambda t: t[1]))

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

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

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

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


这将返回字典中键值对的列表,按值从最高到最低排序:

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

对于按键排序的字典,请使用以下内容:

sorted(d.items(), reverse=True)

返回是元组列表,因为字典本身无法排序。

这可以打印或发送到进一步的计算中。


这是代码:

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}

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}

迭代一个字典并按其值按降序排序:

$ 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

鉴于字典

e = {1:39, 4:34, 7:110, 2:87}

排序

sred = sorted(e.items(), key=lambda value: value[1])

结果

[(4, 34), (1, 39), (2, 87), (7, 110)]

您可以使用lambda函数按值对事物进行排序,并将它们存储在变量中,在本例中使用原始字典进行sred

希望有所帮助!





dictionary