带有预定义顺序的Python顺序字典

时间:2018-10-30 15:56:12

标签: python json dictionary ordereddictionary

接收字典并返回新的有序字典

从api返回的json:

{
    'host': '192.168.0.1',
    'name': 'my_new_name',
    'port': 443,
    'something_more': 'hello'
}

目标:

{
    'name': 'my_new_name',
    'something_more': 'hello',
    'host': '192.168.0.1',
    'port': 443
}

有什么方法可以定义键的顺序?

例如要在目标上实现此订单:

key_order = ('name', 'something_more', 'host', 'port')

谢谢

4 个答案:

答案 0 :(得分:4)

您可以使用列表推导将元组列表提供给collections.OrderedDict

from collections import OrderedDict

d = {'host': '192.168.0.1', 'name': 'my_new_name',
     'port': 443, 'something_more': 'hello'}

key_order = ('name', 'something_more', 'host', 'port')
res = OrderedDict([(k, d[k]) for k in key_order])

OrderedDict([('name', 'my_new_name'),
             ('something_more', 'hello'),
             ('host', '192.168.0.1'),
             ('port', 443)])

适用于Python 2.x及更高版本。对于Python 3.7+,您可以依赖插入顺序并使用常规字典。

答案 1 :(得分:2)

如果您使用的是Python 3.7或更高版本*,则可以保留字典中的项目顺序,因为插入顺序得以保留。创建一个新词典并按照您喜欢的顺序插入项目:

def reorder_items(d, keys):
    d = d.copy() #we're going to destructively modify d, so make a copy first
    result = {}
    for key in keys:
        if key in d:
            result[key] = d.pop(key)
    #the user might not have supplied all the keys belonging to d, 
    #so insert anything we haven't touched yet
    result.update(d)
    return result

d = {
    'host': '192.168.0.1',
    'name': 'my_new_name',
    'port': 443,
    'something_more': 'hello'
}

desired_key_order = ('name', 'something_more', 'host', 'port')
goal = reorder_items(d, desired_key_order)
print(goal)

结果:

{'name': 'my_new_name', 'something_more': 'hello', 'host': '192.168.0.1', 'port': 443}

(*您也可以在CPython 3.6中执行此操作,但这是一个实现细节,不应依赖它)

在3.7之前,您不能直接控制字典中各项的排序方式。但是您可以使用collections.OrderedDict类型。使用上一个代码块中的功能,用result = {}切换result = collections.OrderedDict()


一种更简洁(尽管略微不透明)的方法是:

result = {key:d[key] for category in (desired_key_order, d.keys()) for key in category if key in d}
#or, for versions prior to 3.7,
result = collections.OrderedDict((key, d[key]) for category in (desired_key_order, d.keys()) for key in category if key in d)

这利用了以下事实:可以使用重复的键来构造dict理解和OrderedDict,同时相对于每个键的首次出现保持顺序。

这仍然比jpp的解决方案要长一些,因为它试图更加容错。即使d包含desired_key_order不包含的键,它仍然有效,反之亦然。未指定顺序的项目将在具有指定顺序的项目之后出现在结果中。

答案 2 :(得分:0)

Ordered Dictionary是你需要我的朋友。]

from collections import OrderedDict
d = OrderedDict([
('name', 'my_new_name'),
('something_more', 'hello'),
('host', '192.168.0.1'),
('port', 443)
])

编辑:仅在Python 3.6+中有效。还向OrderedDict提供一个元组列表而不是一个字典,以保持键值对的顺序。

答案 3 :(得分:0)

如果您使用的是Python <3.7,则OrderedDict将保留项目的顺序:

from collections import OrderedDict

d = OrderedDict([
        ('name', 'my_new_name'),
        ('something_more', 'hello'),
        ('host', '192.168.0.1'),
        ('port', 443)
    ])

# OrderedDict([('name', 'my_new_name'), ('something_more', 'hello'), ('host', '192.168.0.1'), ('port', 443)])