【问题标题】:Converting dict to OrderedDict将 dict 转换为 OrderedDict
【发布时间】:2019-01-19 13:42:43
【问题描述】:

我在使用 collections.OrderedDict 类时遇到了一些问题。我在 Raspberry Pi 的 Debian 发行版 Raspbian 上使用 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')])

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

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

【问题讨论】:

  • 注意:OrderedDict 是按插入顺序排序的,而不是字母数字键顺序。

标签: python ordereddictionary


【解决方案1】:

您可以在一行中从旧字典创建有序字典:

from collections import OrderedDict
ordered_dict = OrderedDict(sorted(ship.items())

默认排序键是字典键,所以新的ordered_dict是按照旧字典的键排序的。

【讨论】:

    【解决方案2】:

    使用 dict.items();它可以像下面这样简单:

    ship = collections.OrderedDict(ship.items())
    

    【讨论】:

    • 实际上ship.items() 没有被订购。您可以通过简单地打印 ship.items() 来检查
    【解决方案3】:

    您正在创建一个字典首先,然后将该字典传递给OrderedDict。对于 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 实现必须遵循此行为。请参阅this other answer of mine 了解详细信息,以及在某些情况下您仍可能希望使用OrderedDict() 的原因。

    【讨论】:

    • 好的,OrderedDict 会为我创建字典吗?另外,要打印没有可重现的表示,我可以只打印使用的变量 OrderedDict 吗?即:print ship ??谢谢:)
    • 问题:按照您所描述的方式,OrderedDict 正在制作一个有序的“列表”。这不是违背目的吗?它只是创建一个元素列表,而不是带有键和值的字典......
    • 类型的行为就像两者一样;保留顺序的映射。要创建一个有顺序的,你需要给它按顺序的项目。由于标准 dict(在 PyPI 或 Python 3.6+ 以外的任何东西上)不能做到这一点,所以你给它一个元组列表。一旦OrderedDict创建字典。
    • 听起来混乱是因为假设 OrderedDict “应用”了一个排序,而不是仅仅保留一个排序。我当然认为它会在创建时对输入进行排序——或者 items() 函数将返回排序的项目,无论它们何时插入。相反,它只会保留您提供的任何顺序。
    • @whiterook6: 这不是一个 sorted 字典号。它是一个有序字典,一个记录键值对顺序并让您重新排序这些键值对的字典。将此与列表进行比较,列表是有序的序列
    【解决方案4】:

    大多数时候,当我们需要自定义订单而不是 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

    【讨论】:

      【解决方案5】:

      如果您无法编辑定义 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)
      

      【讨论】:

        猜你喜欢
        • 2019-10-22
        • 1970-01-01
        • 2014-09-23
        • 2019-09-28
        • 1970-01-01
        • 1970-01-01
        • 2018-12-08
        • 2020-08-24
        相关资源
        最近更新 更多