【问题标题】:Convert OrderedDict to normal dict preserving order?将 OrderedDict 转换为正常的字典保留顺序?
【发布时间】:2014-07-20 21:05:45
【问题描述】:

如何在保持相同顺序的同时将OrderedDict 转换为普通字典?

我之所以问这个问题是因为当我从 API 获取数据时,我得到一个 JSON 字符串,我在其中使用 json.loads(str) 返回一个字典。从json.loads(...) 返回的这个字典只是乱序,是随机排序的。另外,我读到OrderedDict 使用起来很慢,所以我想以与原始 JSON 字符串相同的顺序使用常规 dict。

有点题外话:有没有使用json.loads(...) 将JSON 字符串转换为字典,同时在不使用collections.OrderedDict 的情况下保持相同的顺序?

【问题讨论】:

标签: python json string dictionary ordereddictionary


【解决方案1】:

当您将 OrderedDict 转换为普通的 dict 时,您不能保证会保留顺序,因为 dicts 是无序的。这就是为什么 OrderedDict 首先存在的原因。

您似乎也想吃蛋糕,在这里。如果您希望保留 JSON 字符串的顺序,请使用我在 cmets 中链接到的问题的答案将您的 json 字符串直接加载到 OrderedDict 中。但是您必须处理带来的任何性能损失(我不知道该惩罚是什么。对于您的用例来说甚至可以忽略不计。)。如果您想获得最佳性能,只需使用dict。但它将是无序的。

【讨论】:

  • 我明白了,好的。谢谢。我可以使用 OrderedDict,但我不想为此牺牲性能。
  • @user1757703 我会对您的工作负载进行一些测试并比较两者的性能。您可能会担心一个非常小的差异。或者,它可能很大,但只有你尝试过才会知道。不幸的是,如果您绝对需要保持订单,我认为您别无选择,只能接受打击。
  • 我赞成你的答案,但主要是因为问题下的评论中的链接,因为问题实际上是关于保留 JSON 对象中键/值对的顺序——也许你应将评论移至您的一站式购物答案中。
【解决方案2】:

JSON 对象和 Python 字典都是无序的。为了保持顺序,请使用映射到 Python 列表的 JSON 数组。 JSON 数组的元素应该是 JSON 对象。这些将映射到 Python 字典的 Python 列表。

Python 3:

from collections import OrderedDict
import json

# Preserving order in Python dict:
ordered_dict = OrderedDict([
    ('a', 1),
    ('b', 2),
    ('c', 3),
])

# Convert to JSON while preserving order:
ordered_list = [{key: val} for key, val in ordered_dict.items()]
json.dumps(ordered_list)
# '[{"a": 1}, {"b": 2}, {"c": 3}]'

Javascript (JSON):

var orderedListStr = '[{"a": 1}, {"b": 2}, {"c": 3}]';
// We will receive this array of objects with preserved order:
var orderedList = JSON.parse(orderedListStr)

【讨论】:

  • 没错,JSON 对象被定义为无序的名称/值对集合,但是这些对确实以某种顺序出现,并且可以想象出于各种原因想要保留它。从您的回答中的建议中不清楚如何将 JSON 对象转换为执行此操作的数组或列表。
  • 这是一个明显的改进。不幸的是,问题是关于生成字典,而不是列表(所有 列表都是有序的,顺便说一句)。我也认为转换为单元素字典列表与元组列表(即[(key, val) for key, val in ordered_dict.items()])没有任何价值。此外,必须使用列表代替字典可能会对性能产生严重影响,因为查找会变得慢得多(O(n) vs O(1))。无论如何都要为跳出框框思考而投票。 ;-)
  • 我同意没有为 JSON 排序的字典(对象)不是一个深思熟虑的决定。但是这些事情是我们无法控制的。在没有为有序字典提供内置类型的这些问题上,Javascript 比 Python 稍逊一筹。虽然列表的这些元素是单元素字典,但值可能非常复杂,甚至使用相同的列表排序方法嵌套。 Django 最近从元组转向列表,因为测试表明它们具有相同的速度,但列表更灵活。
  • 在 Javascript 客户端,我有时会保留这样的有序数组并将它们恢复为通常的无序 Javascript 对象。它将使用双内存,但是允许两种可能性:以正确的顺序迭代数组并通过散列对象直接访问值。内存很便宜。
  • 似乎您需要做的就是保留一个有序列表/数组,其中包含仅知道它们顺序的键——这不需要双倍的内存。事实上,这就是在将 OrderedDict 添加到 Python 2.4 的标准库之前,有些人实现了自己的 OrderedDict。
猜你喜欢
  • 1970-01-01
  • 2017-09-04
  • 2014-12-01
  • 1970-01-01
  • 2020-08-24
  • 2013-12-08
  • 2020-04-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多