Python order Dict с предопределенным порядком - PullRequest
0 голосов
/ 30 октября 2018

Получите диктовку и верните новую заказанную диктовку

JSON вернулся из API:

{
    '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 голосов
/ 30 октября 2018

Вы можете использовать понимание списка для подачи списка кортежей в 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+ вы можете положиться на порядок вставки и использовать обычный словарь.

0 голосов
/ 30 октября 2018

Если вы используете 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, и наоборот. Элементы, порядок которых не указан, появятся в результате после элементов, для которых указан порядок.

0 голосов
/ 30 октября 2018

Если вы на Python <3.7, <code>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)])
0 голосов
/ 30 октября 2018

Упорядоченный словарь это то, что тебе нужно, мой друг.]

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

Редактировать: это работает только в Python 3.6+. Также введите OrderedDict со списком кортежей вместо словаря, чтобы поддерживать порядок пар ключ-значение.

...