Словари: Как сохранить ключи / значения в том же порядке, как объявлено?

У меня есть словарь, который я объявил в определенном порядке, и я хочу постоянно держать его в этом порядке. Ключи / значения не могут быть сохранены в порядке, основанном на их значении, я просто хочу их в том порядке, в котором я их объявил.

Так что, если у меня есть словарь:

d = {'ac': 33, 'gw': 20, 'ap': 102, 'za': 321, 'bs': 10}

Это не в том порядке, если я его просматриваю или перебираю, есть ли способ убедиться, что Python сохранит явный порядок, в котором я объявил ключи / значения?

11 ответов

Начиная с Python 3.6, стандарт dict Тип поддерживает порядок вставки по умолчанию.

определяющий

d = {'ac':33, 'gw':20, 'ap':102, 'za':321, 'bs':10}

приведет к появлению словаря с ключами в порядке, указанном в исходном коде.

Это было достигнуто путем использования простого массива с целыми числами для разреженной хеш-таблицы, где эти целые числа индексируют в другой массив, в котором хранятся пары ключ-значение (плюс вычисленный хеш). Этот последний массив просто хранит элементы в порядке вставки, и вся комбинация фактически использует меньше памяти, чем реализация, используемая в Python 3.5 и ранее. Смотрите оригинальную идею идеи Раймонда Хеттингера для деталей.

В 3.6 это все еще считалось деталью реализации; смотрите документацию Что нового в Python 3.6:

Сохраняющий порядок аспект этой новой реализации считается деталью реализации, и на него не следует полагаться (это может измениться в будущем, но желательно иметь эту новую реализацию dict в языке в течение нескольких выпусков, прежде чем изменять спецификацию языка. предписывать семантику сохранения порядка для всех текущих и будущих реализаций Python, что также помогает сохранить обратную совместимость со старыми версиями языка, где все еще действует случайный порядок итераций, например, Python 3.5).

Python 3.7 переводит эту деталь реализации в спецификацию языка, поэтому теперь обязательно dict сохраняет порядок во всех реализациях Python, совместимых с этой версией или более новой. Смотрите заявление BDFL.

Вы все еще можете использовать collections.OrderedDict() класс в некоторых случаях, так как он предлагает некоторые дополнительные функции в дополнение к стандартным dict тип. Такие как быть обратимыми (это распространяется на объекты просмотра) и поддерживать переупорядочение (через move_to_end() метод).

from collections import OrderedDict
OrderedDict((word, True) for word in words)

содержит

OrderedDict([('He', True), ('will', True), ('be', True), ('the', True), ('winner', True)])

Если значения True (или любой другой неизменный объект), вы также можете использовать:

OrderedDict.fromkeys(words, True)

Вместо объяснения теоретической части приведу простой пример.

>>> from collections import OrderedDict
>>> my_dictionary=OrderedDict()
>>> my_dictionary['foo']=3
>>> my_dictionary['aol']=1
>>> my_dictionary
OrderedDict([('foo', 3), ('aol', 1)])
>>> dict(my_dictionary)
{'foo': 3, 'aol': 1}

Обратите внимание, что этот ответ относится к версиям Python до Python3.7. CPython 3.6 поддерживает порядок вставки в большинстве случаев в качестве детали реализации. Начиная с Python3.7, было объявлено, что реализации ДОЛЖНЫ поддерживать порядок вставки, чтобы быть совместимыми.


Словари Python неупорядочены. Если вы хотите упорядоченный словарь, попробуйте collection.OrderedDict.

Обратите внимание, что OrderedDict был введен в стандартную библиотеку в python 2.7. Если у вас более старая версия python, вы можете найти рецепты для упорядоченных словарей в ActiveState.

Словари будут использовать порядок, который делает поиск эффективным, и вы не можете изменить это,

Вы можете просто использовать список объектов (кортеж из 2 элементов в простом случае или даже класс) и добавлять элементы в конец. Затем вы можете использовать линейный поиск, чтобы найти элементы в нем.

В качестве альтернативы вы можете создать или использовать другую структуру данных, созданную с целью поддержания порядка.

Вы не можете действительно делать то, что вы хотите со словарем. У вас уже есть словарь d = {'ac':33, 'gw':20, 'ap':102, 'za':321, 'bs':10}создано. Я обнаружил, что не было никакого способа поддерживать порядок, когда он уже создан. Вместо этого я создал файл json с объектом:

{"ac":33,"gw":20,"ap":102,"za":321,"bs":10}

Я использовал:

r = json.load(open('file.json'), object_pairs_hook=OrderedDict)

затем использовали:

print json.dumps(r)

проверять.

Я наткнулся на этот пост, пытаясь выяснить, как заставить OrderedDict работать. PyDev для Eclipse вообще не смог найти OrderedDict, поэтому я решил сделать кортеж из ключевых значений моего словаря так, как мне хотелось бы, чтобы они были упорядочены. Когда мне нужно было вывести свой список, я просто перебрал значения кортежа и вставил повторяющийся "ключ" из кортежа в словарь, чтобы получить мои значения в том порядке, в котором они мне нужны.

пример:

test_dict = dict( val1 = "hi", val2 = "bye", val3 = "huh?", val4 = "what....")
test_tuple = ( 'val1', 'val2', 'val3', 'val4')
for key in test_tuple: print(test_dict[key])

Это немного громоздко, но мне не хватает времени, и это обходной путь, который я нашел.

примечание: подход со списком списков, который предложил кто-то другой, на самом деле не имеет смысла для меня, потому что списки упорядочены и проиндексированы (и также имеют другую структуру, чем словари).

from collections import OrderedDict
list1 = ['k1', 'k2']
list2 = ['v1', 'v2']
new_ordered_dict = OrderedDict(zip(list1, list2))
print new_ordered_dict
# OrderedDict([('k1', 'v1'), ('k2', 'v2')])

Другой альтернативой является использование панд dataframe так как это гарантирует порядок и индекс расположения предметов в подобной диктату структуре.

У меня была похожая проблема при разработке проекта Django. Я не мог использовать OrderedDict, потому что у меня работала старая версия python, поэтому простым решением было использование класса SortedDict в Django:

https://code.djangoproject.com/wiki/SortedDict

Как правило, вы можете создать класс, который будет вести себя как словарь, в основном реализуя методы __contains__, __getitem__, __delitem__, __setitem__ и еще немного. Этот класс может иметь любое поведение, которое вам нравится, например, выделение отсортированного итератора по ключам...

Если вы хотите иметь словарь в определенном порядке, вы также можете создать список списков, где первый элемент будет ключом, а второй элемент будет значением и будет выглядеть следующим образом

>>> list =[[1,2],[2,3]]
>>> for i in list:
...     print i[0]
...     print i[1]

1
2
2
3

Вы можете сделать то же самое, что я сделал для словаря.

Создайте список и пустой словарь:

dictionary_items = {}
fields = [['Name', 'Himanshu Kanojiya'], ['email id', 'hima@gmail.com']]
l = fields[0][0]
m = fields[0][1]
n = fields[1][0]
q = fields[1][1]
dictionary_items[l] = m
dictionary_items[n] = q
print dictionary_items
Другие вопросы по тегам