ChatGPT解决这个技术问题 Extra ChatGPT

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

如何按字典的键对字典进行排序?

示例输入:

{2:3, 1:89, 4:5, 3:0}

期望的输出:

{1:89, 2:3, 3:0, 4:5}
@KarlKnechtel - 我的用例是我有一个 CLI 应用程序,它有一个原始菜单,并且菜单选项在字典中作为键。为了用户的理智,我想按字母顺序显示键。
@Nayuki,鉴于这是一个 Python 问题,我将字典等同于 dict
请注意,字典现在按插入顺序排序(python 3.6+)。下面的一些答案指出了这一点。
@matiasg 请注意,在 Python 3.6 中,保留插入顺序的字典是 CPython 的一个实现细节。在 Python 3.7 中,字典的插入顺序保存正式成为该语言的一部分

S
SuperStormer

注意:对于 Python 3.7+,请参阅此答案

标准 Python 字典是无序的(直到 Python 3.7)。即使您对 (key,value) 对进行了排序,也无法以保留顺序的方式将它们存储在 dict 中。

最简单的方法是使用 OrderedDict,它会记住插入元素的顺序:

In [1]: import collections

In [2]: d = {2:3, 1:89, 4:5, 3:0}

In [3]: od = collections.OrderedDict(sorted(d.items()))

In [4]: od
Out[4]: OrderedDict([(1, 89), (2, 3), (3, 0), (4, 5)])

不要介意 od 的打印方式;它会按预期工作:

In [11]: od[1]
Out[11]: 89

In [12]: od[3]
Out[12]: 0

In [13]: for k, v in od.iteritems(): print k, v
   ....: 
1 89
2 3
3 0
4 5

蟒蛇 3

对于 Python 3 用户,需要使用 .items() 而不是 .iteritems()

In [13]: for k, v in od.items(): print(k, v)
   ....: 
1 89
2 3
3 0
4 5

@achrysochoou:如果那行得通,那一定是幸运的。正如您被告知的那样,常规字典没有排序的概念,无论您分配的键是排序的还是随机的。
对于 python 3.7+:sorted_dict = dict(sorted(unsorted_dict.items()))
python 3.7+ 不需要orderedDict,因为它现在默认订购:-)
来自 python 3.7.4 手册:“在字典上执行 list(d) 会返回字典中使用的所有键的列表,按插入顺序排列”。所以插入顺序是保留的,我们可以依赖。
OrderedDict 是一个半解决方案,因为它保持插入顺序。因此,不能从空字典开始添加项目并期望键按排序顺序。相反,它只能在填充所有项目后用于现有字典,因为 OrderedDict 结构仅适用于插入顺序,而不适用于您可能期望的任何类型的排序。
N
Nils von Barth

字典本身没有这样的订购项目,如果您想按某种顺序打印它们等,这里有一些例子:

在 Python 2.4 及更高版本中:

mydict = {'carl':40,
          'alan':2,
          'bob':1,
          'danny':3}

for key in sorted(mydict):
    print "%s: %s" % (key, mydict[key])

给出:

alan: 2
bob: 1
carl: 40
danny: 3

(Python 2.4 以下:)

keylist = mydict.keys()
keylist.sort()
for key in keylist:
    print "%s: %s" % (key, mydict[key])

来源:http://www.saltycrane.com/blog/2007/09/how-to-sort-python-dictionary-by-keys/


您还可以在 python 2.4+ 中使用 OrderedDict,如 NPE 的回答
如果您使用 items(),您可以像 for key, value in sorted(mydict.items())"
字典本身没有这样的排序项目->不再正确!
怎么回事,能解释一下吗?
@James 见 link
S
ShadowRanger

对于 CPython/PyPy 3.6 和任何 Python 3.7 或更高版本,这很容易通过以下方式完成:

>>> d = {2:3, 1:89, 4:5, 3:0}
>>> dict(sorted(d.items()))
{1: 89, 2: 3, 3: 0, 4: 5}

编写相同内容的另一种方法是使用推导式:{key:d[key] for key in sorted(d.keys())}
伟大的单线!我不知道那个新功能。它适用于我在 Python 3.6.8 上的 Centos 7 中。
这是一个很好的答案。但是不要试图通过将 sorted 括在 {} 中来缩短它,就像在 {sorted(d.items())} 中一样。那只会尝试创建一个集合。
@flow2k 的答案(使用“comprehension”)可以简化:{key:d[key] for key in sorted(d)} 因为 sorted(d) 返回 d 的键的排序列表
@Timo sorted(d.items()) 返回一个可迭代的排序键 &值对,而不是字典
D
Dennis

Python's collections library documentation

>>> from collections import OrderedDict

>>> # regular unsorted dictionary
>>> d = {'banana': 3, 'apple':4, 'pear': 1, 'orange': 2}

>>> # dictionary sorted by key -- OrderedDict(sorted(d.items()) also works
>>> 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)])

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

惊人的!伙计们,如果您想反转顺序(升序到降序),那么您只需添加 reverse=True 例如 OrderedDict(sorted(d.items(), reverse=True, key=lambda t: t[0]))
在 PyCharm 中,无论我使用什么字典,我总是会收到以下警告:Unexpected type(s): (List[str]) Possible types: (Mapping) (Iterable[Tuple[Any, Any]])
G
GrantJ

有许多 Python 模块提供字典实现,这些实现自动按排序顺序维护键。考虑 sortedcontainers 模块,它是纯 Python 和 fast-as-C 实现。还有一个 performance comparison 与其他流行的选项相互进行基准测试。

如果您需要在迭代的同时不断添加和删除键/值对,则使用有序 dict 是一个不合适的解决方案。

>>> from sortedcontainers import SortedDict
>>> d = {2:3, 1:89, 4:5, 3:0}
>>> s = SortedDict(d)
>>> s.items()
[(1, 89), (2, 3), (3, 0), (4, 5)]

SortedDict 类型还支持索引位置查找和删除,这是内置 dict 类型无法实现的。

>>> s.iloc[-1]
4
>>> del s.iloc[2]
>>> s.keys()
SortedSet([1, 2, 4])

u
user3769249

简单地:

d = {2:3, 1:89, 4:5, 3:0}
sd = sorted(d.items())

for k,v in sd:
    print k, v

输出:

1 89
2 3
3 0
4 5

sd 是元组列表,而不是字典。 (虽然仍然有用。)
我相信你的打印语句需要()。打印 (k,v)
对于 python 3,您只需要 ()。print k, v 在 python 2 中工作得很好,因为 print 是关键字,而不是 python 2 中的函数。
G
Guangyang Li

Python 字典在 Python 3.6 之前是无序的。在 Python 3.6 的 CPython 实现中,字典保持插入顺序。从 Python 3.7 开始,这将成为一种语言特性。

在 Python 3.6 (https://docs.python.org/3.6/whatsnew/3.6.html#whatsnew36-compactdict) 的更新日志中:

这个新实现的顺序保留方面被认为是一个实现细节,不应依赖(这可能会在未来发生变化,但在更改语言规范之前,希望在几个版本中使用该语言的这个新 dict 实现为所有当前和未来的 Python 实现强制要求保持顺序的语义;这也有助于保持与随机迭代顺序仍然有效的旧版本语言的向后兼容性,例如 Python 3.5)。

在 Python 3.7 (https://docs.python.org/3.7/tutorial/datastructures.html#dictionaries) 的文档中:

对字典执行 list(d) 会按插入顺序返回字典中使用的所有键的列表(如果要对其进行排序,只需使用 sorted(d) 代替)。

因此与以前的版本不同,您可以在 Python 3.6/3.7 之后对 dict 进行排序。如果要对包含子字典的嵌套字典进行排序,可以执行以下操作:

test_dict = {'a': 1, 'c': 3, 'b': {'b2': 2, 'b1': 1}}

def dict_reorder(item):
    return {k: dict_reoder(v) if isinstance(v, dict) else v for k, v in sorted(item.items())}

reordered_dict = dict_reorder(test_dict)

https://gist.github.com/ligyxy/f60f0374defc383aa098d44cfbd318eb


我喜欢这个,但你的字典理解中有 sort_dict(),应该是 dict_reoder()
B
Brian

正如其他人所提到的,字典本质上是无序的。但是,如果问题只是以有序方式显示字典,您可以覆盖字典子类中的 __str__ 方法,并使用此字典类而不是内置的 dict。例如。

class SortedDisplayDict(dict):
   def __str__(self):
       return "{" + ", ".join("%r: %r" % (key, self[key]) for key in sorted(self)) + "}"


>>> d = SortedDisplayDict({2:3, 1:89, 4:5, 3:0})
>>> d
{1: 89, 2: 3, 3: 0, 4: 5}

请注意,这不会改变密钥的存储方式、迭代它们时它们返回的顺序等,只是它们在 print 或 python 控制台中的显示方式。


t
tschesseket

找到了另一种方式:

import json
print json.dumps(d, sort_keys = True)

upd:1.这也对嵌套对象进行排序(感谢@DanielF)。 2. python 字典是无序的,因此这仅适用于打印或分配给 str。


但这也会对嵌套对象的键进行排序,这可能是不需要的。
请注意,这仅对字典进行排序,而不是列表,例如 dict.keys() 不会被排序,因为它是一个列表。
E
Evgeny Tryastsin

在 Python 3 中。

>>> D1 = {2:3, 1:89, 4:5, 3:0}
>>> for key in sorted(D1):
    print (key, D1[key])

1 89
2 3
3 0
4 5

p
pr94

一个简单的方法来做到这一点:

d = {2:3, 1:89, 4:5, 3:0}

s = {k : d[k] for k in sorted(d)}

s
Out[1]: {1: 89, 2: 3, 3: 0, 4: 5} 

仅适用于 python 3.7+,其中 dict 是 OrderedDict。
@kwarnke Pedantic,但 dict 与 Python 3.7+ 中的 OrderedDict 不同,尽管 dict 当然是在 3.7+ 中排序的
a
alphazwest

这里有很多答案已经展示了对 Python 字典进行排序的流行方法。我想我会为那些从谷歌来这里寻找非标准想法的人添加一些不太明显的方法。

示例字典:d = {2: 'c', 1: 'b', 0: 'a', 3: 'd'}

字典理解

# Converts to list, sorts, re-converts to dict
{k: v for k, v in sorted(list(d.items()))}

使用 Lambda

排序并不总是严格按照升序或降序进行排序。更多条件排序,结合lamdas使用上述方法:

{k: v for k, v in sorted(d.items(), key=lambda v: ord(v[1]))}

更多示例

这个线程已经有足够的好例子了。有关更多示例,以及 Python 中排序字典的边缘案例和奇怪之处check out this article


对于字典列表理解,它对我不起作用我需要用 sorted(d.items()) 替换 sorted(list(d))(在 python 3.8 上)
@ihoupert 不只是你。我应该只是复制/粘贴我的版本,而不是尝试重新输入。它肯定需要那里的 .items() 调用。
我有一个类似的问题。感谢@ihoupert,我不得不使用 .items()
P
Pang

您可以根据您的问题通过按键对当前字典进行排序来创建新字典。

这是你的字典

d = {2:3, 1:89, 4:5, 3:0}

通过使用 lambda 函数对该 d 进行排序来创建一个新字典 d1

d1 = dict(sorted(d.items(), key = lambda x:x[0]))

d1 应该是 {1:89, 2:3, 3:0, 4:5},根据 d 中的键排序。


您甚至不需要指定排序键。 d1 = dict(sorted(d.items())) 可以正常工作
为什么这不是最佳答案?
A
Atul Arvind

在这里,我找到了一些最简单的解决方案,可以使用 pprint 按键对 python 字典进行排序。例如。

>>> x = {'a': 10, 'cd': 20, 'b': 30, 'az': 99} 
>>> print x
{'a': 10, 'b': 30, 'az': 99, 'cd': 20}

但是在使用 pprint 时,它将返回排序的字典

>>> import pprint 
>>> pprint.pprint(x)
{'a': 10, 'az': 99, 'b': 30, 'cd': 20}

S
Sree

有一种简单的方法可以对字典进行排序。

根据你的问题,

解决方案是:

c={2:3, 1:89, 4:5, 3:0}
y=sorted(c.items())
print y

(其中 c 是您的字典的名称。)

该程序给出以下输出:

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

就像你想要的那样。

另一个例子是:

d={"John":36,"Lucy":24,"Albert":32,"Peter":18,"Bill":41}
x=sorted(d.keys())
print x

给出输出:['Albert', 'Bill', 'John', 'Lucy', 'Peter']

y=sorted(d.values())
print y

给出输出:[18, 24, 32, 36, 41]

z=sorted(d.items())
print z

给出输出:

[('Albert', 32), ('Bill', 41), ('John', 36), ('Lucy', 24), ('Peter', 18)]

因此,通过将其更改为键、值和项目,您可以像您想要的那样打印。希望这会有所帮助!


m
m3.b

我发现对字典进行排序的一种简单方法是创建一个新字典,该方法基于已排序的键:您要排序的字典的值项。如果要对 dict = {} 进行排序,请使用相关方法检索其所有项目,使用 sorted() 函数对它们进行排序,然后创建新字典。

这是使用字典理解的代码:

sorted_dict = {k:v for k,v in sorted(dict.items())}

j
jax

将生成您想要的内容:

 D1 = {2:3, 1:89, 4:5, 3:0}

 sort_dic = {}

 for i in sorted(D1):
     sort_dic.update({i:D1[i]})
 print sort_dic


{1: 89, 2: 3, 3: 0, 4: 5}

但这不是执行此操作的正确方法,因为,它可以用不同的字典显示出不同的行为,这是我最近学到的。因此,蒂姆在我在这里分享的查询的回复中提出了完美的方法。

from collections import OrderedDict
sorted_dict = OrderedDict(sorted(D1.items(), key=lambda t: t[0]))

“使用不同的字典显示不同的行为”是什么意思? sorted 无法处理的“独特行为”是什么?
M
Mehdi Abbassi

以下是建议解决方案的性能:

from collections import OrderedDict
from sortedcontainers import SortedDict
import json

keys = np.random.rand(100000)
vals = np.random.rand(100000)

d = dict(zip(keys, vals))

timeit SortedDict(d)
#45.8 ms ± 780 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

timeit sorted(d.items())
#91.9 ms ± 707 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

timeit OrderedDict(sorted(d.items(), key=lambda x: x[0]))
#93.7 ms ± 1.52 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

timeit dict(sorted(dic.items()))
#113 ms ± 824 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

timeit OrderedDict(sorted(dic.items()))
#122 ms ± 2.65 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

timeit json.dumps(d, sort_keys=True)
#259 ms ± 9.42 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

正如我们所见,Grant Jenks's solution 是迄今为止最快的。


l
lallolu

我认为最简单的方法是按键对字典进行排序并将排序后的键:值对保存在一个新的字典中。

dict1 = {'renault': 3, 'ford':4, 'volvo': 1, 'toyota': 2} 
dict2 = {}                  # create an empty dict to store the sorted values
for key in sorted(dict1.keys()):
    if not key in dict2:    # Depending on the goal, this line may not be neccessary
        dict2[key] = dict1[key]

为了更清楚:

dict1 = {'renault': 3, 'ford':4, 'volvo': 1, 'toyota': 2} 
dict2 = {}                  # create an empty dict to store the sorted     values
for key in sorted(dict1.keys()):
    if not key in dict2:    # Depending on the goal, this line may not be  neccessary
        value = dict1[key]
        dict2[key] = value

Y
Yash Shah

我想出了单行字典排序。

>> a = {2:3, 1:89, 4:5, 3:0}
>> c = {i:a[i] for i in sorted(a.keys())}
>> print(c)
{1: 89, 2: 3, 3: 0, 4: 5}
[Finished in 0.4s]

希望这会有所帮助。


R
Ramashish Baranwal

Python dicts 是无序的。通常,这不是问题,因为最常见的用例是进行查找。

做您想做的最简单的方法是创建一个 collections.OrderedDict 以按排序顺序插入元素。

ordered_dict = collections.OrderedDict([(k, d[k]) for k in sorted(d.keys())])

如果您需要迭代,正如上面其他人所建议的那样,最简单的方法是迭代排序的键。例子-

打印按键排序的值:

# create the dict
d = {k1:v1, k2:v2,...}
# iterate by keys in sorted order
for k in sorted(d.keys()):
    value = d[k]
    # do something with k, value like print
    print k, value

获取按键排序的值列表:

values = [d[k] for k in sorted(d.keys())]

for k,value in sorted(d.items()): 更好:避免在循环中再次按键访问字典
B
Booboo

此函数将按其键对任何字典递归进行排序。也就是说,如果字典中的任何值也是字典,它也将按其键排序。如果您在 CPython 3.6 或更高版本上运行,则可以进行简单的更改以使用 dict 而不是 OrderedDict

from collections import OrderedDict

def sort_dict(d):
    items = [[k, v] for k, v in sorted(d.items(), key=lambda x: x[0])]
    for item in items:
        if isinstance(item[1], dict):
            item[1] = sort_dict(item[1])
    return OrderedDict(items)
    #return dict(items)

H
Hafiz Muhammad Shafiq

最简单的解决方案是你应该得到一个 dict 键的列表,然后按顺序遍历 dict。例如

a1 = {'a':1, 'b':13, 'd':4, 'c':2, 'e':30}
a1_sorted_keys = sorted(a1, key=a1.get, reverse=True)
for r in a1_sorted_keys:
    print r, a1[r]

以下将是输出(降序)

e 30
b 13
d 4
c 2
a 1

P
PeterB

对于问题的表述方式,这里的大多数答案都是正确回答。

然而,考虑到事情应该如何真正完成,考虑到几十年和几十年的计算机科学,我完全惊讶的是这里实际上只有 one answer(来自 GrantJ 用户)建议使用排序的关联容器(sortedcontainers),它根据插入点处的键对元素进行排序。

这将避免每次调用 sort(...)(至少 O(N*log(N)),其中 N 是元素数量)大量性能影响(从逻辑上讲,这适用于此处建议使用的所有此类解决方案sort(...))。请注意,对于所有此类解决方案,每次需要按排序AFTER访问集合时,都需要调用 sort(...) 通过添加/删除元素对其进行修改...


S
Saeid

伙计们,你让事情变得复杂......这真的很简单

from pprint import pprint
Dict={'B':1,'A':2,'C':3}
pprint(Dict)

输出是:

{'A':2,'B':1,'C':3}

赞成是因为我不知道 pprint 排序字典来显示它们,但是 OP 确实询问了从未排序到排序的字典“去”的问题,即 OP 似乎想要一些在内存中保持排序的东西,也许对于一些需要排序键的算法
此方法不允许链式赋值,因为 pprint 没有返回值。 >>> adict = {'B':1,'A':2,'C':3} >>> ppdict = pprint(adict) {'A': 2, 'B': 1, 'C': 3} >>> ppdict.type() Traceback(最近一次调用最后):文件“”,第 1 行,在 AttributeError:'NoneType' 对象没有属性'type'
M
Mohammad Mahjoub
from operator import itemgetter
# if you would like to play with multiple dictionaries then here you go:
# Three dictionaries that are composed of first name and last name.
user = [
    {'fname': 'Mo', 'lname': 'Mahjoub'},
    {'fname': 'Abdo', 'lname': 'Al-hebashi'},
    {'fname': 'Ali', 'lname': 'Muhammad'}
]
#  This loop will sort by the first and the last names.
# notice that in a dictionary order doesn't matter. So it could put the first name first or the last name first. 
for k in sorted (user, key=itemgetter ('fname', 'lname')):
    print (k)

# This one will sort by the first name only.
for x in sorted (user, key=itemgetter ('fname')):
    print (x)

M
Mahdi Ghelichi
dictionary = {1:[2],2:[],5:[4,5],4:[5],3:[1]}

temp=sorted(dictionary)
sorted_dict = dict([(k,dictionary[k]) for i,k in enumerate(temp)])

sorted_dict:
         {1: [2], 2: [], 3: [1], 4: [5], 5: [4, 5]}

J
Jesuisme

2.7 中两种方法的时序比较表明它们几乎相同:

>>> setup_string = "a = sorted(dict({2:3, 1:89, 4:5, 3:0}).items())"
>>> timeit.timeit(stmt="[(k, val) for k, val in a]", setup=setup_string, number=10000)
0.003599141953657181

>>> setup_string = "from collections import OrderedDict\n"
>>> setup_string += "a = OrderedDict({1:89, 2:3, 3:0, 4:5})\n"
>>> setup_string += "b = a.items()"
>>> timeit.timeit(stmt="[(k, val) for k, val in b]", setup=setup_string, number=10000)
0.003581275490432745 

C
Community

或使用 pandas

演示:

>>> d={'B':1,'A':2,'C':3}
>>> df=pd.DataFrame(d,index=[0]).sort_index(axis=1)
   A  B  C
0  2  1  3
>>> df.to_dict('int')[0]
{'A': 2, 'B': 1, 'C': 3}
>>> 

看:

整个熊猫文档的文档


u
user7070507
l = dict.keys()
l2 = l
l2.append(0)
l3 = []
for repeater in range(0, len(l)):
    smallnum = float("inf")
    for listitem in l2:
        if listitem < smallnum:
            smallnum = listitem
    l2.remove(smallnum)
    l3.append(smallnum)
l3.remove(0)
l = l3

for listitem in l:
    print(listitem)

还有 14 个其他答案。您能否解释一下您的代码以及为什么它可能比其他解决方案更好?
Downvoted - 带有短的无意义变量名 l、l2、l3 的非常不可读的代码。似乎是在不了解python标准函数的情况下尝试一种间接且低效的算法,并且在原始帖子中的小示例上进行测试时无论如何都不起作用。