Słownik Pythona: czy klucze () i wartości () są zawsze tej samej kolejności?


312

Wygląda na to, że listy zwracane przez keys()i values()metody słownika są zawsze mapowaniem 1 na 1 (zakładając, że słownik nie jest zmieniany między wywołaniem 2 metod).

Na przykład:

>>> d = {'one':1, 'two': 2, 'three': 3}
>>> k, v = d.keys(), d.values()
>>> for i in range(len(k)):
    print d[k[i]] == v[i]

True
True
True

Jeśli nie zmienisz słownika między dzwonieniem keys()a dzwonieniem values(), czy błędem jest założenie, że powyższa pętla for zawsze będzie wyświetlać True? Nie mogłem znaleźć żadnej dokumentacji potwierdzającej to.


1
W CPython 3.7 (i więcej, przypuszczalnie) możesz polegać na kolejności iteracji słownika odpowiadającej kolejności wstawiania. mail.python.org/pipermail/python-dev/2017-December/151283.html
BallpointBen

@BallpointBen jest w CPython 3.6 i nowszych wersjach oraz we wszystkich innych implementacjach Pythona począwszy od Python 3.7
Boris

Odpowiedzi:


353

Znajdź to:

Jeśli items(), keys(), values(), iteritems(), iterkeys(), i itervalues()nazywane są bez interweniujących modyfikacji do słownika, listy będą bezpośrednio odpowiadać.

Na dokumentacji 2.x oraz dokumentacji 3.x .


5
najwyraźniej stwierdzenie w dokumentacji 3.x jest jaśniejsze: „kolejność elementów będzie bezpośrednio odpowiadać”
Shaohua Li

4
Brakuje tego tekstu w dokumentacji 3.7. Mogę tylko założyć, że „Dict zachowuje kolejność wstawiania” w 3.7: mail.python.org/pipermail/python-dev/2017-December/151283.html
EliadL

80

Tak, to, co zaobserwowałeś, jest rzeczywiście gwarantowaną właściwością - listy kluczy (), wartości () i pozycje () zwracają się w odpowiedniej kolejności, jeśli dyktando nie zostanie zmienione. iterkeys () i c również iterują w tej samej kolejności, co odpowiednie listy.


1
Jednak w przypadku, gdy lista jest zmienione, Pandy dataframeoferuje alternatywę, gdzie elementy mogą być aktualizowane lub usuwane, a kolejność i rozmieszczenie indeks elementów w dict-jak struktury pozostają stałe.
Ville,

48

Tak, jest to gwarantowane w Pythonie 2.x :

Jeśli widoki kluczy, wartości i elementów są iterowane bez pośrednich modyfikacji słownika, kolejność elementów będzie bezpośrednio odpowiadać.



6

Dobre odniesienia do dokumentów. Oto w jaki sposób możesz zagwarantować zamówienie niezależnie od dokumentacji / realizacji:

k, v = zip(*d.iteritems())

1
W python3.x użyj dict.items ()
Good Will


4

Co do tego jest warte, niektóre ciężko używane kody produkcyjne, które napisałem, oparte są na tym założeniu i nigdy nie miałem z tym problemu. Wiem, że to nie prawda :-)

Jeśli nie chcesz ryzykować, użyłbym iteritems (), jeśli możesz.

for key, value in myDictionary.iteritems():
    print key, value

-2

Nie byłem zadowolony z tych odpowiedzi, ponieważ chciałem upewnić się, że eksportowane wartości mają taką samą kolejność, nawet przy użyciu różnych nagrań.

Tutaj z góry określasz kolejność kluczy, zwracane wartości będą zawsze miały tę samą kolejność, nawet jeśli dykt zmieni się lub użyjesz innego dykta.

keys = dict1.keys()
ordered_keys1 = [dict1[cur_key] for cur_key in keys]
ordered_keys2 = [dict2[cur_key] for cur_key in keys]
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.