Словарь добавления Python избавится от алфавитного упорядочения, сохраните исходную последовательность [duplicate]

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

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

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

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

213
задан 4 June 2018 в 06:04

10 ответов

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)
139
ответ дан 15 August 2018 в 15:35
  • 1
    Стоит отметить, конечно, что «неизменяемая» часть не является жестким и быстрым правилом, который Python будет применять - «только» & quot; хорошая идея. – lvc 11 June 2012 в 19:37
  • 2
    имейте в виду, что такие решения, как: OrderedDict(FUTURE=[], TODAY=[], PAST=[]) не работают, когда упоминается aproach: OrderedDict([('FUTURE', []), ('TODAY', []), ('PAST', [])]) будет поддерживать порядок. – andilabs 5 June 2014 в 18:47
  • 3
    @andi У меня возникла еще одна проблема: при использовании jsonify, OrderedDict кажется потерянным при заказе при генерации данных json. Как решить эту проблему? – tyan 31 March 2016 в 05:57
  • 4
    github.com/pallets/flask/issues/974 это может быть использовано для решения проблемы. – tyan 31 March 2016 в 06:01

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

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

2
ответ дан 15 August 2018 в 15:35

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

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

1
2
2
3
2
ответ дан 15 August 2018 в 15:35
  • 1
    Это не «словарь», потому что вы не можете искать элементы по их ключу, не просматривая всю коллекцию (принимая время O (n)). – BHSPitMonkey 1 May 2014 в 05:09
  • 2
    Да, это не словарь, но, в зависимости от ситуации, он может обеспечить правильное решение проблемы с оригинальным плакатом. – SunSparc 26 August 2015 в 00:21
  • 3
    он не сказал точно, как мы хотели, просто чтобы иметь возможность заказать их =), так как всегда есть много способов сделать одно. – pelos 22 March 2018 в 19:54

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

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

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

9
ответ дан 15 August 2018 в 15:35

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

Определение

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

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

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

В 3.6 это все еще считалось деталью реализации; см. исходную идею идеи Раймонда Хеттингера :

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

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

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

91
ответ дан 15 August 2018 в 15:35
  • 1
    Это приятное (изменение) поведение, похоже, не задокументировано в docs.python.org/3/library/stdtypes.html#dict - я искал намек на заказ. docs.python.org/3/tutorial/datastructures.html#dictionaries упоминает «неупорядоченный», «произвольный порядок». – handle 16 May 2017 в 13:17
  • 2
    @handle, и это потому, что это деталь реализации, как отмечает Крис. [D0] Что нового в Python 3.6 docs упоминают об этом. – Martijn Pieters♦ 16 May 2017 в 13:20
  • 3
    Это решило мою проблему. Я использовал Python для сортировки и выравнивания тонны вещей из электронной таблицы, которая кормила другую систему. Порядок был критическим. Я обновился до версии 3.6.4 (последняя версия Hombrew), и она вышла в порядок, не возившись с ней! – Wrenbjor 15 January 2018 в 20:57
  • 4
    @Chris_Rands: совершенно верно, добавил, что в. – Martijn Pieters♦ 10 April 2018 в 00:24

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

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

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

20
ответ дан 15 August 2018 в 15:35
  • 1
    см. сообщение @ martijn выше. Начиная с версии python 3.6, dict поддерживает порядок вставки. – tpk 17 July 2017 в 13:28
  • 2
    @ 2943 Осторожно. Пока что это только для CPython, и это документировано как деталь реализации. pypy использует эту оптимизацию на некоторое время ... Обратите внимание, что это также означает, что когда другие разработчики (например, Jython) получают доступ к v3.6, им не нужно сохранять порядок вставки, чтобы быть совместимыми. Наконец, это означает, что сохранение заказа может быть отменено, когда Raymond Hettinger придумает следующее поколение оптимизации для dict. IOW, на данный момент, если вы хотите заказать dict, вы должны использовать OrderedDict. – mgilson 18 July 2017 в 16:53
  • 3
    спасибо за предложение – tpk 19 July 2017 в 10:39

Вы не можете делать то, что хотите, со словарем. У вас уже есть словарь 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)

to проверить.

5
ответ дан 15 August 2018 в 15:35
  • 1
    Так почему бы не начать с OrderedDict из списка? Файл JSON ничего действительно не добавляет. – Martijn Pieters♦ 13 June 2017 в 09:21
  • 2
    Да, список более полезен для поддержания порядка, но ответ был связан с вопросом о заказе словарей. Просто давая людям знать об ограничениях использования словаря и давая им возможную работу, если им по какой-то причине нужно использовать словарь. – nealous3 14 June 2017 в 13:33
  • 3
    Но эта часть уже покрыта гораздо более старыми ответами, относящимися к 2012 году. – Martijn Pieters♦ 14 June 2017 в 13:38

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

2
ответ дан 15 August 2018 в 15:35

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

example:

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])

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

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

7
ответ дан 15 August 2018 в 15:35
  • 1
    Отличное решение. Я буду использовать его для записи json в файл, всегда в том же порядке. – Hrvoje T 28 April 2018 в 00:53

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

>>> from collections import OrderedDict
>>> my_dictionary=OrderedDict()
>>> my_dictionary['foo']=3
>>> my_dictionary['aol']=1
>>> my_dictionary
OrderedDict([('foo', 3), ('aol', 1)])
126
ответ дан 15 August 2018 в 15:35
  • 1
    Есть ли способ переназначить OrderedDict как тип Dict? – tyan 31 March 2016 в 05:50
  • 2
    OrderedDict действительно решает проблему, но ... в этом конкретном примере вы получаете точно такой же результат, используя стандартный словарь – Tonechas 25 April 2016 в 22:08
  • 3
    @Tonechas: Я просто попробовал пример со стандартным словарем и получил {'aol': 1, 'foo': 3}. Поэтому я считаю, что это хороший иллюстративный пример. – twasbrillig 3 May 2016 в 23:13
  • 4
    Урок для всех: он был обнаружен (я думаю, около версии 2.4), что предсказуемое хеширование Python может привести к уязвимостям системы безопасности , поэтому теперь нет никакой гарантии, что даже два разных прогона одного и того же кода будут дать тот же порядок в стандартном dict. – holdenweb 1 September 2016 в 11:19
  • 5
    Почему мы не можем передать какой-то формат порядка, который мы хотим массово инициализировать нашими значениями? Вместо того, чтобы назначать в каждой строке одно значение? (Python2.7) – JavaSa 6 June 2017 в 14:43

Другие вопросы по тегам:

Похожие вопросы: