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

时间:2009-12-08 15:53:36

标签: python sorting dictionary

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

所以如果我有字典:

d = {'ac': 33, 'gw': 20, 'ap': 102, 'za': 321, 'bs': 10}

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

13 个答案:

答案 0 :(得分:164)

from collections import OrderedDict
OrderedDict((word, True) for word in words)

包含

OrderedDict([('He', True), ('will', True), ('be', True), ('the', True), ('winner', True)])

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

OrderedDict.fromkeys(words, True)

答案 1 :(得分:156)

我不是解释理论部分,而是给出一个简单的例子。

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

答案 2 :(得分:147)

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

定义

d = {'ac':33, 'gw':20, 'ap':102, 'za':321, 'bs':10}

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

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

在3.6中,这仍被视为实施细节;请参阅What's New in Python 3.6 documentation

  

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

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

在某些情况下,您可能仍希望使用collections.OrderedDict() class,因为它在标准dict类型之上提供了一些其他功能。例如reversible(这延伸到view objects),并支持重新排序(通过move_to_end() method)。

答案 3 :(得分:30)

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


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

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

答案 4 :(得分:11)

字典将使用一个使搜索更有效的订单,而你无法改变它,

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

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

答案 5 :(得分:7)

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

示例:

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

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

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

答案 6 :(得分:5)

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

{"ac":33,"gw":20,"ap":102,"za":321,"bs":10}

我用过:

r = json.load(open('file.json'), object_pairs_hook=OrderedDict)

然后使用:

print json.dumps(r)

验证。

答案 7 :(得分:1)

通常,您可以设计一个行为类似字典的类,主要是实现方法__contains____getitem____delitem____setitem__等等。该类可以具有您喜欢的任何行为,例如将已排序的迭代器隐藏在键上...

答案 8 :(得分:1)

开发Django项目时遇到了类似的问题。我无法使用OrderedDict,因为我运行的是旧版本的python,所以简单的解决方案就是使用Django的SortedDict类:

https://code.djangoproject.com/wiki/SortedDict

答案 9 :(得分:1)

如果您想按特定顺序添加字典,还可以创建列表列表,其中第一项是键,第二项是值 并且看起来像这样 例子

>>> list =[[1,2],[2,3]]
>>> for i in list:
...     print i[0]
...     print i[1]

1
2
2
3

答案 10 :(得分:1)

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

答案 11 :(得分:0)

您可以做与字典一样的事情。

创建列表并清空字典:

dictionary_items = {}
fields = [['Name', 'Himanshu Kanojiya'], ['email id', 'hima@gmail.com']]
l = fields[0][0]
m = fields[0][1]
n = fields[1][0]
q = fields[1][1]
dictionary_items[l] = m
dictionary_items[n] = q
print dictionary_items

答案 12 :(得分:0)

另一种替代方法是使用熊猫dataframe,因为它可以保证像dict这样的结构中物品的顺序和索引位置。