将dict转换为OrderedDict


138

我在collections.OrderedDict上课时遇到了一些麻烦。我在Raspbian(Raspberry Pi的Debian发行版)上使用Python 2.7。我正在尝试打印两个字典,以便进行文本冒险的比较(并排)。该顺序对于准确比较至关重要。不管我尝试什么,词典都以通常的无序方式打印。

这是我在RPi上执行的操作所得到的:

import collections

ship = {"NAME": "Albatross",
         "HP":50,
         "BLASTERS":13,
         "THRUSTERS":18,
         "PRICE":250}

ship = collections.OrderedDict(ship)

print ship
# OrderedDict([('PRICE', 250), ('HP', 50), ('NAME', 'Albatross'), ('BLASTERS', 13), ('THRUSTERS', 18)])

显然有些不对劲,因为它正在打印函数调用并将键和值组放入嵌套列表中。

这是通过在PC上运行类似内容得到的:

import collections

Joe = {"Age": 28, "Race": "Latino", "Job": "Nurse"}
Bob = {"Age": 25, "Race": "White", "Job": "Mechanic", "Random": "stuff"}

#Just for clarity:
Joe = collections.OrderedDict(Joe)
Bob = collections.OrderedDict(Bob)

print Joe
# OrderedDict([('Age', 28), ('Race', 'Latino'), ('Job', 'Nurse')])
print Bob
# OrderedDict([('Age', 25), ('Race', 'White'), ('Job', 'Mechanic'), ('Random', 'stuff')])

这次是有秩序的,但是它不应该打印其他东西吗?(将其放入列表并显示函数调用。)

我在哪里犯错误?它与pi的pi版本无关,因为它只是Linux的版本。


3
注意:OrderedDict按插入顺序排序,而不是字母数字键顺序。
el.pescado

Answers:


214

您正在创建一个字典第一,然后传递一个字典来的OrderedDict。对于<3.6 (*)的 Python版本,到您这样做时,排序将不再正确。dict本质上是无序的。

改为传递一个元组序列:

ship = [("NAME", "Albatross"),
        ("HP", 50),
        ("BLASTERS", 13),
        ("THRUSTERS", 18),
        ("PRICE", 250)]
ship = collections.OrderedDict(ship)

打印时看到的OrderedDict是它的表示形式,它是完全正确的。OrderedDict([('PRICE', 250), ('HP', 50), ('NAME', 'Albatross'), ('BLASTERS', 13), ('THRUSTERS', 18)])只是以可复制的方式向您显示的内容OrderedDict


(*):在CPython 3.6实现中,该dict类型已更新为使用内存效率更高的内部结构,该结构具有保留插入顺序的快乐副作用,并且通过扩展,问题中显示的代码可以正常工作。从Python 3.7开始,Python语言规范已更新,要求所有Python实现都必须遵循此行为。有关详细信息以及在某些情况下为什么仍要使用的原因请参见我的其他答案OrderedDict()


好吧,OrderedDict会为我创建字典吗?另外,要打印没有可再现的表示形式,是否可以仅打印用于其中的变量OrderedDict?即: print ship ?? 谢谢:)
pythonpiboy

3
问题:按照您描述的方式,OrderedDict正在创建一个有序的“列表”。那不是目的吗?它只是创建一个元素列表,而不是带有键和值的字典...
pythonpiboy

9
该类型的行为就像两者一样。保留顺序的映射。要创建带有订单的商品,您需要为其提供订单商品。由于标准字典(除PyPI或Python 3.6+以外的其他字典)无法做到这一点,因此您可以给它提供一个元组列表。一旦OrderedDict创建一本字典。
马丁·彼得斯

4
听起来好像是因为假设一个OrderedDict“应用”了一个排序,而不是仅仅保留一个排序。我当然认为它会在创建时对输入进行排序-或者items()函数将返回排序后的项目,无论何时插入它们。相反,它只是保留您提供的任何订购。
whiterook6 '16

2
@ whiterook6:它不是排序字典。这是一个有序字典,该字典记录键值对的顺序,并允许您对这些对重新排序。将此与有序序列的列表进行比较。
马丁·彼得斯

36

如果您无法在定义dict的地方编辑这部分代码,您仍然可以随时以所需的任何方式对其进行排序,如下所示:

from collections import OrderedDict

order_of_keys = ["key1", "key2", "key3", "key4", "key5"]
list_of_tuples = [(key, your_dict[key]) for key in order_of_keys]
your_dict = OrderedDict(list_of_tuples)

11

在大多数情况下,当我们需要自定义订单而不是ASC等通用订单时,我们会使用OrderedDict。

这是建议的解决方案:

import collections
ship = {"NAME": "Albatross",
         "HP":50,
         "BLASTERS":13,
         "THRUSTERS":18,
         "PRICE":250}

ship = collections.OrderedDict(ship)

print ship


new_dict = collections.OrderedDict()
new_dict["NAME"]=ship["NAME"]
new_dict["HP"]=ship["HP"]
new_dict["BLASTERS"]=ship["BLASTERS"]
new_dict["THRUSTERS"]=ship["THRUSTERS"]
new_dict["PRICE"]=ship["PRICE"]


print new_dict

这将输出:

OrderedDict([('PRICE', 250), ('HP', 50), ('NAME', 'Albatross'), ('BLASTERS', 13), ('THRUSTERS', 18)])
OrderedDict([('NAME', 'Albatross'), ('HP', 50), ('BLASTERS', 13), ('THRUSTERS', 18), ('PRICE', 250)])

注意:删除条目时,新排序的词典将保持其排序顺序。但是当添加新密钥时,密钥会附加到末尾,并且不会保留排序。(Official doc


2

使用dict.items(); 它可以很简单,如下所示:

ship = collections.OrderedDict(ship.items())
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.