Словари: Как сохранить ключи / значения в том же порядке, как объявлено?
У меня есть словарь, который я объявил в определенном порядке, и я хочу постоянно держать его в этом порядке. Ключи / значения не могут быть сохранены в порядке, основанном на их значении, я просто хочу их в том порядке, в котором я их объявил.
Так что, если у меня есть словарь:
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:
Как правило, вы можете создать класс, который будет вести себя как словарь, в основном реализуя методы __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