Kolejność kluczy w słownikach


106

Kod:

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

print l

To drukuje ['a', 'c', 'b']. Nie jestem pewien, jak metoda keys()określa kolejność słów kluczowych w l . Chciałbym jednak móc pobrać słowa kluczowe we „właściwej” kolejności. Lista stworzyłaby oczywiście właściwa kolejność ['a', 'b', 'c'].


4
Jeśli słowniki Pythona są takie jak większość, w rzeczywistości są to tablice skrótów. Oznacza to między innymi, że kolejność kluczy nie jest gwarantowana ani nawet określona. W szczególności nie zapamiętałby kolejności, w jakiej dodawane są klucze.
cHao

4
@cHao: To w istocie oznacza, że ​​twój program będzie niezdeterministyczny, jeśli zapętlisz elementy w słowniku?
HelloGoodbye

5
@HelloGoodbye: Nie posunąłbym się tak daleko; nadal istnieje bardzo przewidywalne zachowanie. Każda pełna iteracja powoduje wyświetlenie dokładnie jednej pary klucz / wartość. W większości języków zobaczysz je za każdym razem w tej samej kolejności. O ile dokumenty nie gwarantują konkretnego zamówienia, nie powinieneś liczyć na to, że będzie to zamówienie, które chcesz. (Niektóre języki (takie jak Perl) w rzeczywistości nieco losują kolejność - rzekomo ze względów bezpieczeństwa, ale myślę, że tak naprawdę jest to tylko po to, aby uwolnić Cię od nawyku polegania na nieokreślonym zachowaniu. :) Nie sądzę, że Python jest całkiem to zło, ale eh ...)
cHao

1
Kolejność będzie taka sama, pod warunkiem, że dykt nie został zmodyfikowany. Z podręcznika: „Jeśli pozycje (), klucze (), wartości (), iteritems (), iterkeys () i itervalues ​​() są wywoływane bez żadnych modyfikacji słownika, listy będą bezpośrednio odpowiadać. par (wartość, klucz) za pomocą zip (): pairs = zip (d.values ​​(), d.keys ()). "
steveayre

2
@sfranky Myślę, że steveayre miał na myśli to, że kolejność jest taka sama między tym, co uzyskujesz za pomocą różnych wymienionych metod, a nie taka sama, jak kolejność, w której zapisano elementy.
bli

Odpowiedzi:


81

Możesz użyć OrderedDict (wymaga Pythona 2.7) lub nowszego.

Zauważ też, że OrderedDict({'a': 1, 'b':2, 'c':3})to nie zadziała, ponieważ dictutworzony w programie {...}już zapomniałeś o kolejności elementów. Zamiast tego chcesz użyć OrderedDict([('a', 1), ('b', 2), ('c', 3)]).

Jak wspomniano w dokumentacji, w przypadku wersji niższych niż Python 2.7 można użyć tego przepisu.


18
Pamiętaj, że kolejność w OrderedDict jest wstawienie zamówienie; klucze pojawią się w kolejności alfabetycznej tylko wtedy, gdy wstawisz je w ten sposób.
Hugh Bothwell,

to właśnie pokazał jako uproszczony przykład; może, ale nie musi, mieć jakikolwiek związek z tym, jak zamierza go używać. Wcześniej spotkałem ludzi, którzy oczekiwali, że OrderedDict zwróci dowolne wstawki w uporządkowanej kolejności, więc uznałem, że powinienem zwrócić na to uwagę.
Hugh Bothwell,

129

Python 3.7+

W Pythonie 3.7.0 natura zachowania kolejności wstawiania dictobiektów została zadeklarowana jako oficjalna część specyfikacji języka Python. Dlatego możesz na tym polegać.

Python 3.6 (CPython)

Począwszy od Pythona 3.6, w przypadku implementacji języka Python w języku CPython słowniki domyślnie utrzymują kolejność wstawiania . Jest to jednak uważane za szczegół implementacji; powinieneś nadal używać, collections.OrderedDictjeśli chcesz, aby kolejność wstawiania była gwarantowana w innych implementacjach Pythona.

Python> = 2.7 i <3.6

Użyj collections.OrderedDictklasy, gdy potrzebujesz elementu, dictktóry pamięta kolejność wstawianych elementów.


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

Użyj posortowanej funkcji , która sortuje przekazaną iterację.

.keys()Metoda zwraca klucze w dowolnej kolejności.


12
To nie działa, jeśli chcesz uzyskać oryginalne zamówienie i nie zostało ono posortowane.
Simon

13

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

„Metoda keys () obiektu słownika zwraca listę wszystkich kluczy używanych w słowniku w dowolnej kolejności (jeśli chcesz, aby były posortowane, po prostu zastosuj do tego funkcję sort ())”.


12

Po prostu posortuj listę, kiedy chcesz jej użyć.

l = sorted(d.keys())

1

Chociaż kolejność nie ma znaczenia, ponieważ słownik jest hashmap. Zależy to od kolejności wpychania:

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

wyjście:
dla string abbc, klucze to dict_keys (['a', 'b', 'c'])
dla string cbab, klucze to dict_keys (['c', 'b', 'a'])


1
Słownik w Pythonie jest zamawiany tylko od wersji 3.6+ sprawdź to
Crivella
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.