字典:如何保持键/值与声明的顺序相同?

rof*_*fle 292 python sorting dictionary

我有一个字典,我按特定顺序声明,并希望始终保持该顺序.键/值不能根据它们的值按顺序保存,我只是按照我声明的顺序想要它.

所以,如果我有字典:

d = {'ac': 33, 'gw': 20, 'ap': 102, 'za': 321, 'bs': 10}
Run Code Online (Sandbox Code Playgroud)

如果我查看它或迭代它,它是不是按顺序,有没有办法确保Python将保持我声明键/值的显式顺序?

Mar*_*ers 185

从Python 3.6开始,标准dict类型默认维护插入顺序.

定义

d = {'ac':33, 'gw':20, 'ap':102, 'za':321, 'bs':10}
Run Code Online (Sandbox Code Playgroud)

将生成一个字典,其中包含源代码中列出的顺序的键.

这是通过对稀疏散列表使用带整数的简单数组来实现的,其中这些整数索引到另一个存储键值对的数组(加上计算的散列).后一个数组恰好以插入顺序存储项目,并且整个组合实际上使用的内存少于Python 3.5及之前使用的实现.有关详细信息,请参阅Raymond Hettinger原创帖子.

在3.6中,这仍然被认为是一个实现细节; 请参阅Python 3.6文档中的新功能:

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

Python 3.7将此实现细节提升为语言规范,因此现在必须dict在与该版本或更新版本兼容的所有Python实现中保留顺序.请参阅BDFL的声明.

在某些情况下,您可能仍希望使用collections.OrderedDict()该类,因为它在标准dict类型之上提供了一些附加功能.例如可逆(这扩展到视图对象),并支持重新排序(通过该move_to_end()方法).

  • @ManuelSelva 约定是:除非*明确*声明某些内容是 CPython 实现细节,否则文档中标准类型功能的描述使该功能成为语言规范的一部分。 (3认同)
  • @ naught101:不,这*确实适用于字典的创建。在Python 3.7及更高版本中,使用问题**中所示的dict显示可保证按顺序列出这些键。写入的键值对从左到右插入,因为[语言规范保证](https://docs.python.org/3/reference/expressions.html#dictionary-displays):*如果用逗号-给出了键/数据对的分离序列,它们从左到右进行评估以定义字典的条目*。[dict()文档](https://docs.python.org/3/library/stdtypes.html#dict)甚至包括一个示例。 (2认同)
  • @ManuelSelva [3.7 新文档提到了它](https://docs.python.org/3/whatsnew/3.7.html)(链接到我引用的电子邮件)。[字典视图对象部分](https://docs.python.org/3/library/stdtypes.html#dictionary-view-objects)进一步记录了迭代顺序(在`iter(dictview)`下:*键和值是按插入顺序迭代。*并且*字典顺序保证是插入顺序。*)。 (2认同)
  • @ManuelSelva 数据模型文档的[标准类型层次结构部分](https://docs.python.org/3/reference/datamodel.html#the-standard-type-hierarchy)也涵盖了该主题(*字典保留插入order,这意味着键将按照它们在字典中顺序添加的顺序生成。*)。 (2认同)

eum*_*iro 171

from collections import OrderedDict
OrderedDict((word, True) for word in words)
Run Code Online (Sandbox Code Playgroud)

包含

OrderedDict([('He', True), ('will', True), ('be', True), ('the', True), ('winner', True)])
Run Code Online (Sandbox Code Playgroud)

如果值是True(或任何其他不可变对象),您还可以使用:

OrderedDict.fromkeys(words, True)
Run Code Online (Sandbox Code Playgroud)

  • 要注意解决方案如:`OrderedDict(FUTURE = [],TODAY = [],PAST = [])``````or or or or or or or or or or or or or or or or or or or or or or or or or or ',[]),('过去',[])])`将保持秩序. (10认同)
  • Python3.7现在默认情况下已将dict排序。https://mail.python.org/pipermail/python-dev/2017-December/151283.html (5认同)
  • 当然,值得注意的是,"不可变"部分并不是Python强制执行的硬性规则 - 它只是一个好主意. (2认同)
  • @andi我遇到另一个问题,当使用jsonify时,在生成json数据时,OrderedDict似乎丢失了顺序。是否可以解决此问题? (2认同)

Moh*_*bas 161

我将举一个简单的例子,而不是解释理论部分.

>>> from collections import OrderedDict
>>> my_dictionary=OrderedDict()
>>> my_dictionary['foo']=3
>>> my_dictionary['aol']=1
>>> my_dictionary
OrderedDict([('foo', 3), ('aol', 1)])
>>> dict(my_dictionary)
{'foo': 3, 'aol': 1}
Run Code Online (Sandbox Code Playgroud)

  • 有没有办法像Dict类型那样批量分配OrderedDict? (16认同)
  • 这里就为大家上了一课:它被发现(我觉得周围的2.4版本)Python的[预见的散列可能引起的安全漏洞(http://bugs.python.org/issue13703),所以现在也不能保证,即使相同代码的两个不同运行将在标准字典中给出相同的顺序. (3认同)
  • `OrderedDict`确实解决了问题,但是...在此特定示例中,使用标准字典可获得完全相同的结果 (2认同)
  • @Tonechas:我刚用标准字典试了一下这个例子,得到了`{'aol':1,'foo':3}`所以我认为这是一个很好的说明性例子. (2认同)

mgi*_*son 33

请注意,此答案适用于python3.7之前的python版本.CPython 3.6在大多数情况下维护插入顺序作为实现细节.从Python3.7开始,已经声明实现必须保持插入顺序符合要求.


python词典是无序的.如果您想要一个有序的字典,请尝试collections.OrderedDict.

请注意,OrderedDict被引入到python 2.7中的标准库中.如果你有旧版本的python,你可以在ActiveState上找到有序词典的配方.


Fir*_*cer 12

字典将使用一个使搜索有效的订单,你不能改变它,

您可以使用对象列表(在简单的情况下,甚至是类中的2元素元组),并将项目追加到最后.然后,您可以使用线性搜索来查找其中的项目.

或者,您可以创建或使用为维护订单而创建的不同数据结构.


smu*_*ace 7

我试图找出如何让OrderedDict工作时遇到这篇文章.PyDev for Eclipse根本找不到OrderedDict,所以我最终决定制作我的字典键值的元组,因为我希望它们被命令.当我需要输出我的列表时,我只是迭代了元组的值并将迭代的'key'从元组插入到字典中,以按照我需要的顺序检索我的值.

例:

test_dict = dict( val1 = "hi", val2 = "bye", val3 = "huh?", val4 = "what....")
test_tuple = ( 'val1', 'val2', 'val3', 'val4')
for key in test_tuple: print(test_dict[key])
Run Code Online (Sandbox Code Playgroud)

这有点麻烦,但我时间紧迫,这是我提出的解决方法.

注意:列表列表方法,其他人建议对我没有意义,因为列表是有序和索引的(并且也是与字典不同的结构).


nea*_*us3 6

你不能用字典真正做你想做的事.您已经d = {'ac':33, 'gw':20, 'ap':102, 'za':321, 'bs':10}创建了字典.我发现一旦创建它就没有办法保持秩序.我做的是用对象制作一个json文件:

{"ac":33,"gw":20,"ap":102,"za":321,"bs":10}
Run Code Online (Sandbox Code Playgroud)

我用了:

r = json.load(open('file.json'), object_pairs_hook=OrderedDict)
Run Code Online (Sandbox Code Playgroud)

然后使用:

print json.dumps(r)
Run Code Online (Sandbox Code Playgroud)

核实.


小智 5

from collections import OrderedDict
list1 = ['k1', 'k2']
list2 = ['v1', 'v2']
new_ordered_dict = OrderedDict(zip(list1, list2))
print new_ordered_dict
# OrderedDict([('k1', 'v1'), ('k2', 'v2')])
Run Code Online (Sandbox Code Playgroud)