Порядок клавіш у словниках


101

Код:

d = {'a': 0, 'b': 1, 'c': 2}
l = d.keys()

print l

Це друкує ['a', 'c', 'b']. Я не впевнений, як метод keys()визначає порядок ключових слів у межах l . Однак я хотів би мати можливість відновити ключові слова у "належному" порядку. Правильний порядок, звичайно, створив би список ['a', 'b', 'c'].


3
Якщо словники Python подібні до більшості, вони насправді є хеш-таблицями. Крім усього іншого, це означає, що порядок клавіш не гарантований і навіть не визначений. Зокрема, він не запам’ятав би порядок додавання ключів.
cHao

3
@cHao: Це по суті означає, що ваша програма буде недетермінованою, якщо ви переходите на елементи в словнику?
HelloGoodbye

4
@HelloGoodbye: Я б не зайшов так далеко; там все ще дуже передбачувана поведінка. Кожна повна ітерація бачить точно одну з кожної пари ключ / значення. І на більшості мов ви навіть бачитимете їх в однаковому порядку кожного разу. Якщо документи не гарантують конкретне замовлення, ви не повинні розраховувати на те, що це замовлення, яке ви хочете. (Деякі мови (наприклад, Perl) насправді дещо рандомізують замовлення - нібито з міркувань безпеки, але я думаю, що це насправді просто позбавити вас від звички покладатися на невстановлену поведінку. :) Я не думаю, що Python досить це зло, але е ...)
cHao

1
Порядок буде таким самим, якщо диктування не було змінено. З посібника: "Якщо елементи (), ключі (), значення (), iteritems (), iterkeys () та itervalues ​​() викликаються без втручання в словник, списки будуть безпосередньо відповідати. Це дозволяє створювати пар (значення, ключ) за допомогою zip (): пари = zip (d.values ​​(), d.keys ()). "
steveayre

2
@sfranky Я думаю, що мав на увазі steveayre, це те, що порядок однаковий між тим, що ви отримуєте, використовуючи різні згадані методи, а не той самий, що і замовник, в якому були написані елементи.
блі

Відповіді:


78

Ви можете використовувати OrderedDict (потрібен Python 2.7) або вище.

Також зауважте, що OrderedDict({'a': 1, 'b':2, 'c':3})це не спрацює, оскільки створений dictвами файл {...}вже забув порядок елементів. Натомість ви хочете використовувати OrderedDict([('a', 1), ('b', 2), ('c', 3)]).

Як зазначено в документації, для версій, нижчих за Python 2.7, ви можете використовувати цей рецепт.


18
Майте на увазі, порядок OrderedDict - це порядок вставки ; клавіші вийдуть в алфавітному порядку, лише якщо ви вставили їх таким чином.
Х'ю Ботвелл

це те, що він показав як спрощений приклад; він може мати або не мати ніякого відношення до того, як він насправді планує ним користуватися. Раніше я стикався з людьми, які очікували, що OrderedDict поверне довільні вставки у відсортованому порядку, і тому я відчув, що повинен на це вказати.
Х'ю Ботвелл

119

Python 3.7+

У Python 3.7.0 характер збереження порядків вставки dictоб'єктів оголошено офіційною частиною специфікації мови Python. Тому ви можете від цього залежати.

Python 3.6 (CPython)

Починаючи з Python 3.6, для реалізації CPython Python словники підтримують порядок вставки за замовчуванням. Це, однак, вважається детальною частиною реалізації; ви все одно повинні використовувати, collections.OrderedDictякщо ви хочете впорядкувати вставку, що гарантовано в інших реалізаціях Python.

Python> = 2,7 та <3,6

Використовуйте collections.OrderedDictклас, коли вам потрібно dictзапам'ятовувати порядок вставлених елементів.


48
>>> print sorted(d.keys())
['a', 'b', 'c']

Використовуйте відсортовану функцію , яка сортує переданий ітерабел.

.keys()Метод повертає ключі в довільному порядку.


12
Це не працює, якщо потрібно оригінальне замовлення, і воно не було відсортовано.
Саймон

12

Просто сортуйте список, коли ви хочете його використовувати.

l = sorted(d.keys())

12

З http://docs.python.org/tutorial/datastructures.html :

"Метод keys () об'єкта словника повертає список усіх ключів, що використовуються у словнику, у довільному порядку (якщо ви хочете його сортувати, просто застосуйте до нього функцію sorted ())."


1

Хоча порядок не має значення, оскільки словник має хеш-карту. Це залежить від порядку, як його натискають:

s = 'abbc'
a = 'cbab'

def load_dict(s):
    dict_tmp = {}
    for ch in s:
        if ch in dict_tmp.keys():
            dict_tmp[ch]+=1
        else:
            dict_tmp[ch] = 1
    return dict_tmp

dict_a = load_dict(a)
dict_s = load_dict(s)
print('for string %s, the keys are %s'%(s, dict_s.keys()))
print('for string %s, the keys are %s'%(a, dict_a.keys()))

висновок:
для рядка abbc ключами є dict_keys (['a', 'b', 'c'])
для рядка cbab, ключі - dict_keys (['c', 'b', 'a'])


1
Словник у python - це вставка, замовлена ​​лише у версії 3.6+. Перевірте це
Crivella
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.