Jak indeksować do słownika?

101

Mam słownik poniżej:

colors = {
    "blue" : "5",
    "red" : "6",
    "yellow" : "8",
}

Jak zindeksować pierwszy wpis w słowniku?

colors[0]zwróci z KeyErroroczywistych powodów.

Harpal
źródło
4
Co oznacza „pierwszy”? Słowniki nie mają uporządkowania.
S.Lott
4
Słowniki są teraz wstawiane w kolejności od wersji Python 3.7 Sprawdź to: stackoverflow.com/questions/39980323/…
Nikita Alkhovik
Powiązane: Efektywny
dostęp
1
@ S.Lott Założę się, że nie zapytałby, gdyby wiedział, że są nieuporządkowane :).
user7778287

Odpowiedzi:

119

Słowniki są nieuporządkowane w wersjach Pythona do Pythona 3.6 włącznie. Jeśli nie zależy Ci na kolejności wpisów i mimo wszystko chcesz uzyskać dostęp do kluczy lub wartości według indeksu, możesz użyć d.keys()[i]i d.values()[i]lub d.items()[i]. (Zwróć uwagę, że te metody tworzą listę wszystkich kluczy, wartości lub elementów w Pythonie 2.x. Jeśli więc potrzebujesz ich więcej niż raz, przechowuj listę w zmiennej, aby poprawić wydajność).

Jeśli zależy Ci na kolejności wpisów, zaczynając od Pythona 2.7 możesz użyć collections.OrderedDict. Lub użyj listy par

l = [("blue", "5"), ("red", "6"), ("yellow", "8")]

jeśli nie potrzebujesz dostępu za pomocą klucza. (Nawiasem mówiąc, dlaczego twoje ciągi liczbowe?)

W Pythonie 3.7 normalne słowniki są uporządkowane, więc nie musisz ich OrderedDictjuż używać (ale nadal możesz - to w zasadzie ten sam typ). Implementacja CPythona w Pythonie 3.6 już zawierała tę zmianę, ale ponieważ nie jest to część specyfikacji języka, nie można na niej polegać w Pythonie 3.6.

Sven Marnach
źródło
3
W Pythonie 2 użyj d.iterkeys().next()zamiast, d.keys()[0]aby sprawdzić jeden z kluczy bez usuwania go. Jeśli słownik jest ogromny, będzie miał duży wpływ na wydajność. To samo dotyczy wartości i przedmiotów. W Pythonie 2.7 możesz także używać obiektów widoku dict
simleo
47
W Pythonie 3 wywołania te zwracają raczej widok niż aktualną listę, więc powinieneś zawinąć je w wywołanie list (), w przeciwnym razie zobaczysz: „TypeError: obiekt 'dict_values' nie obsługuje indeksowania”. Zobacz to pytanie SO: stackoverflow.com/questions/17431638/…
stifin
4
Tylko mała poprawka: nie można indeksować elementów (), przynajmniej nie w Pythonie 3.
John Strong
2
Ta odpowiedź jest nieaktualna dla Pythona 3.6+, zobacz odpowiedź @Pasha poniżej.
hans
1
@hans Ta odpowiedź jest nieaktualna dla Pythona 3.7, ale nie dla Pythona 3.6, ponieważ chroniąca porządek natura słowników jest szczegółem implementacji CPythona w tej wersji Pythona, a nie oficjalną częścią języka. Zaktualizuję odpowiednio tę odpowiedź.
Sven Marnach
123

Jeśli ktoś nadal patrzy na to pytanie, obecnie przyjęta odpowiedź jest już nieaktualna:

Od wersji Python 3.7 * słowniki zachowują kolejność , to znaczy, że teraz zachowują się dokładnie tak, jak collections.OrderedDictkiedyś. Niestety, nadal nie ma dedykowanej metody indeksowania do keys()/ values()ze słownika, więc pobranie pierwszego klucza / wartości w słowniku można wykonać w następujący sposób

first_key = list(colors)[0]
first_val = list(colors.values())[0]

lub alternatywnie (pozwala to uniknąć tworzenia instancji widoku kluczy w liście):

def get_first_key(dictionary):
    for key in dictionary:
        return key
    raise IndexError

first_key = get_first_key(colors)
first_val = colors[first_key]

Jeśli potrzebujesz n-tego klucza, to podobnie

def get_nth_key(dictionary, n=0):
    if n < 0:
        n += len(dictionary)
    for i, key in enumerate(dictionary.keys()):
        if i == n:
            return key
    raise IndexError("dictionary index out of range") 

(* CPython 3.6 już zawierał dykty zamówione, ale był to tylko szczegół implementacji. Specyfikacja języka obejmuje dykty zamówione od wersji 3.7).

Basza
źródło
Czy mogę podać link do odpowiedniej dokumentacji?
Amir Afianian
3

Zajmowanie się elementem słownika jest jak siedzenie na osiołku i radość z jazdy.

Z reguły w Pythonie SŁOWNIK jest uporządkowany

Jeśli jest

dic = {1: "a", 2: "aa", 3: "aaa"}

Teraz przypuśćmy, że jeśli pójdę tak dic[10] = "b", to nie będzie tak dodawać zawsze

dic = {1:"a",2:"aa",3:"aaa",10:"b"}

Może tak

dic = {1: "a", 2: "aa", 3: "aaa", 10: "b"}

Lub

dic = {1: "a", 2: "aa", 10: "b", 3: "aaa"}

Lub

dic = {1: "a", 10: "b", 2: "aa", 3: "aaa"}

Albo jakąkolwiek taką kombinację.

Zatem praktyczna zasada jest taka, że SŁOWNIK nie ma porządku !

Raj Damani
źródło
to jest bardzo trudne ... Podoba mi się!
Alex Liu 33214
2

Jeśli potrzebujesz uporządkowanego słownika, możesz użyć odict .

Utku Zihnioglu
źródło
odict nie obsługuje indeksowania do keys (), values ​​() lub items ().
Konstantin,
2

w rzeczywistości znalazłem nowatorskie rozwiązanie, które naprawdę mi pomogło.Jeśli jesteś szczególnie zainteresowany indeksem określonej wartości na liście lub zestawie danych, możesz po prostu ustawić wartość słownika na ten indeks !:

Tylko patrz:

list = ['a', 'b', 'c']
dictionary = {}
counter = 0
for i in list:
   dictionary[i] = counter
   counter += 1

print(dictionary) # dictionary = {'a':0, 'b':1, 'c':2}

Teraz dzięki mocy hashmap możesz ciągnąć indeks swoich wpisów w stałym czasie (czyli o wiele szybciej)

user3368835
źródło
1

och, to jest trudne. Zasadniczo masz tutaj dwie wartości dla każdego elementu. Następnie próbujesz zadzwonić do nich, podając numer jako klucz. Niestety, jedna z Twoich wartości jest już ustawiona jako klucz!

Spróbuj tego:

colors = {1: ["blue", "5"], 2: ["red", "6"], 3: ["yellow", "8"]}

Teraz możesz wywoływać klucze według numerów, tak jakby były indeksowane jak lista. Możesz również odwołać się do koloru i numeru, podając ich pozycję na liście.

Na przykład,

colors[1][0]
// returns 'blue'

colors[3][1]
// returns '8'

Oczywiście będziesz musiał wymyślić inny sposób śledzenia lokalizacji każdego koloru. Może możesz mieć inny słownik, który przechowuje klucz każdego koloru jako jego wartość.

colors_key = {'blue': 1, 'red': 6, 'yllow': 8}

Wtedy będziesz mógł również sprawdzić klucz kolorów, jeśli zajdzie taka potrzeba.

colors [colors_key ['blue']] [0] zwróci wartość 'blue'

Coś w tym stylu.

A potem, kiedy już to robisz, możesz stworzyć dyktando z wartościami liczbowymi jako kluczami, aby zawsze móc ich użyć do wyszukania swoich kolorów, wiesz, jeśli potrzebujesz.

wartości = {5: [1, 'niebieski'], 6: [2, 'czerwony'], 8: [3, 'żółty']}

Następnie (colors [colors_key [values ​​[5] [1]]] [0]) zwróci wartość „blue”.

Lub możesz użyć listy list.

Powodzenia!

Godfreyluck
źródło
0

Nie możesz, ponieważ dictjest nieuporządkowany. możesz użyć, .popitem()aby uzyskać dowolny przedmiot, ale spowoduje to usunięcie go z dyktowania.

Ignacio Vazquez-Abrams
źródło
next(iter(d.items()))( .iteritems()w Pythonie 2) daje również dowolny element (to samo w moich testach, co ma sens, ponieważ popitem można zaimplementować za pomocą tego), ale nie usunie elementu.