Dostęp do elementów słownika Pythona według indeksu


118

Rozważ taki dyktando

mydict = {
  'Apple': {'American':'16', 'Mexican':10, 'Chinese':5},
  'Grapes':{'Arabian':'25','Indian':'20'} }

Jak mogę na przykład uzyskać dostęp do określonego elementu tego słownika? na przykład chciałbym wydrukować pierwszy element po pewnym sformatowaniu pierwszego elementu Apple, który w naszym przypadku jest tylko „amerykański”?

Informacje dodatkowe Powyższa struktura danych została utworzona poprzez analizę pliku wejściowego w funkcji Pythona. Po utworzeniu pozostaje jednak taki sam dla tego biegu.

Używam tej struktury danych w mojej funkcji.

Więc jeśli plik ulegnie zmianie, przy następnym uruchomieniu tej aplikacji zawartość pliku będzie inna, a zatem zawartość tej struktury danych będzie inna, ale format będzie taki sam. Więc widzisz, że w mojej funkcji nie wiem, czy pierwszy element w Apple jest „amerykański” lub cokolwiek innego, więc nie mogę bezpośrednio użyć klucza „amerykański”.


2
Czy możesz podać przykład oczekiwanego wyniku?
Björn Pollex

3
Co tak naprawdę chcesz zrobić z tą strukturą? Czy znasz klawisze dyktowania (w twoim przykładzie „Jabłko” i „Winogrona”)? A może wiesz tylko, że dostaniesz dyktando?
juanchopanza

6
Nie dzwoń do swojego słownika dict. Słowo „dict” jest już słowem kluczowym w Pythonie. Użyj czegoś innego, na przykład mydict.
Rick wspiera Monikę

Uwaga: to pytanie dotyczy dostępu do elementów dyktowania według indeksu , co nie ma sensu, ponieważ dykty są nieuporządkowane. W przypadku pytania o dostęp do elementów w zagnieżdżonym dyktacie, zobacz Python - dostęp do wartości zagnieżdżonych w słownikach .
Aran-Fey

@ Aran-Fey: nieuporządkowane rzeczy mają wewnętrzny porządek. Unordered! = Brak zamówienia.
Jamie Marshall

Odpowiedzi:


122

Biorąc pod uwagę, że jest to słownik, dostęp do niego uzyskuje się za pomocą klawiszy. Pobierając słownik przechowywany w „Apple”, wykonaj następujące czynności:

>>> mydict["Apple"]
{'American': '16', 'Mexican': 10, 'Chinese': 5}

Aby dowiedzieć się, ilu z nich to Amerykanie (16), zrób tak:

>>> mydict["Apple"]["American"]
'16'

9
Jak można to zrobić dynamicznie, nie znając głębi elementów?
Ethan Bierlein

3
Co dokładnie chciałbyś wiedzieć? Możesz uzyskać klucze słownika, .keys()aby mieć do nich dostęp dynamicznie.
Morten Kristensen

3
Na przykład, jeśli masz słownik o nieznanej głębokości, np. Słownik zagnieżdżony, i masz element "n"na nieznanej głębokości, przechowywany w nieznanym elemencie.
Ethan Bierlein

1
To bardzo szerokie pytanie. Biorąc pod uwagę strukturę danych, możesz napisać funkcję lub klasę, która będzie ją odpowiednio obsługiwać. Być może mógłbyś dostarczyć klucz i strategię poszukiwania klucza.
Morten Kristensen

1
@EthanBierlein użyj: 'for key, value in dictionary.iteritems ()', aby mieć dostęp zarówno do klucza, jak i wartości
danius

25

Jeśli pytanie brzmi, jeśli wiem, że mam dyktando zawierające „Apple” jako owoc i „American” jako rodzaj jabłka, użyłbym:

myDict = {'Apple': {'American':'16', 'Mexican':10, 'Chinese':5},
          'Grapes':{'Arabian':'25','Indian':'20'} }


print myDict['Apple']['American']

jak sugerowali inni. Jeśli zamiast tego pojawia się pytanie, nie wiesz, czy `` Apple '' jako owoc i `` amerykański '' jako typ `` Apple '' istnieje, gdy wczytujesz dowolny plik do swojej struktury danych dyktowania, możesz zrobić coś takiego:

print [ftype['American'] for f,ftype in myDict.iteritems() if f == 'Apple' and 'American' in ftype]

lub jeszcze lepiej, aby nie powtarzać niepotrzebnie całego dyktowania, jeśli wiesz, że tylko Apple ma typ amerykański:

if 'Apple' in myDict:
    if 'American' in myDict['Apple']:
        print myDict['Apple']['American']

We wszystkich tych przypadkach nie ma znaczenia, w jakiej kolejności słowniki faktycznie przechowują wpisy. Jeśli naprawdę martwisz się o zamówienie, możesz rozważyć użycie OrderedDict:

http://docs.python.org/dev/library/collections.html#collections.OrderedDict


20

Jak zauważyłem twój opis, po prostu wiesz, że twój parser poda ci słownik, że jego wartości są również słownikiem:

sampleDict = {
              "key1": {"key10": "value10", "key11": "value11"},
              "key2": {"key20": "value20", "key21": "value21"}
              }

Musisz więc iterować po swoim słowniku nadrzędnym. Jeśli chcesz wydrukować lub uzyskać dostęp do wszystkich pierwszych kluczy słownika na sampleDict.values()liście, możesz użyć czegoś takiego:

for key, value in sampleDict.items():
    print value.keys()[0]

Jeśli chcesz tylko uzyskać dostęp do pierwszego klucza pierwszej pozycji w sampleDict.values(), może to być przydatne:

print sampleDict.values()[0].keys()[0]

Jeśli użyjesz przykładu, który podałeś w pytaniu, mam na myśli:

sampleDict = {
              'Apple': {'American':'16', 'Mexican':10, 'Chinese':5},
              'Grapes':{'Arabian':'25','Indian':'20'}
              }

Dane wyjściowe dla pierwszego kodu to:

American
Indian

Wynik dla drugiego kodu to:

American

10

Jako bonus chciałbym zaproponować inne rozwiązanie problemu. Wydaje się, że masz do czynienia ze słownikami zagnieżdżonymi, co jest zwykle uciążliwe, zwłaszcza gdy musisz sprawdzić, czy istnieje klucz wewnętrzny.

Istnieje kilka interesujących bibliotek dotyczących tego na pypi, oto szybkie wyszukiwanie .

W twoim konkretnym przypadku dict_digger wydaje się odpowiedni.

>>> import dict_digger
>>> d = {
  'Apple': {'American':'16', 'Mexican':10, 'Chinese':5},
  'Grapes':{'Arabian':'25','Indian':'20'} 
}

>>> print(dict_digger.dig(d, 'Apple','American'))
16
>>> print(dict_digger.dig(d, 'Grapes','American'))
None

8

Możesz użyć, dict['Apple'].keys()[0]aby uzyskać pierwszy klucz ze Applesłownika, ale nie ma gwarancji, że tak będzie American. Kolejność kluczy w słowniku może się zmieniać w zależności od zawartości słownika i kolejności dodawania kluczy.


chyba że używasz OrderedDictw collectionsbibliotece
Escachator

7

Wiem, że to ma 8 lat, ale wygląda na to, że nikt nie przeczytał i nie odpowiedział na pytanie.

Możesz wywołać .values ​​() na dykt, aby uzyskać listę wewnętrznych dykt i uzyskać do nich dostęp przez indeks.

>>> mydict = {
...  'Apple': {'American':'16', 'Mexican':10, 'Chinese':5},
...  'Grapes':{'Arabian':'25','Indian':'20'} }

>>>mylist = list(mydict.values())
>>>mylist[0]
{'American':'16', 'Mexican':10, 'Chinese':5},
>>>mylist[1]
{'Arabian':'25','Indian':'20'}

>>>myInnerList1 = list(mylist[0].values())
>>>myInnerList1
['16', 10, 5]
>>>myInnerList2 = list(mylist[1].values())
>>>myInnerList2
['25', '20']

2
interesujące, próbowałem tego i dostałem 'dict_values' object does not support indexing . Zgadnij, że ta odpowiedź wymaga aktualizacji, ponieważ musisz zawinąć dict_values, aby odzyskać listę
Yuca

1
@Yucca - Miałeś rację, nie testowałem swojego kodu. Odpowiedź została zaktualizowana
Jamie Marshall



1

Niewiele osób wydaje się, pomimo wielu odpowiedzi na to pytanie, wskazać, że słowniki są nieuporządkowanymi mapowaniami, a więc (aż do błogosławieństwa kolejności wstawiania w Pythonie 3.7) idea „pierwszego” hasła w słowniku dosłownie powstała bezsens. A nawet dostęp do pliku OrderedDictmożna uzyskać tylko za pomocą indeksu liczbowego, używając takich brzydoty, jak mydict[mydict.keys()[0]](tylko Python 2, ponieważ w Pythonie 3 keys()jest iteratorem nieskryptowalnym).

Od 3,7 roku i w praktyce także w 3,6 - wtedy wprowadzono nowe zachowanie, ale nie uwzględniono go w specyfikacji języka do 3.7 - iteracja po klawiszach, wartościach lub elementach dyktatu (i, jak sądzę, set also) zwróci najpierw najmniej niedawno wstawione obiekty. Nadal nie ma prostego sposobu, aby uzyskać do nich dostęp za pomocą numerycznego indeksu wstawiania.

Jeśli chodzi o kwestię wybierania i „formatowania” elementów, jeśli znasz klucz, który chcesz pobrać ze słownika, normalnie użyłbyś klucza jako indeksu dolnego, aby go pobrać ( my_var = mydict['Apple']).

Jeśli naprawdę chcesz mieć możliwość indeksowania pozycji według numeru pozycji (ignorując fakt, że numer konkretnego wpisu będzie się zmieniał w miarę wstawiania), wówczas odpowiednią strukturą byłaby prawdopodobnie lista dwuelementowych krotek. Zamiast

mydict = {
  'Apple': {'American':'16', 'Mexican':10, 'Chinese':5},
  'Grapes':{'Arabian':'25','Indian':'20'} }

możesz użyć:

mylist = [
    ('Apple', {'American':'16', 'Mexican':10, 'Chinese':5}),
    ('Grapes', {'Arabian': '25', 'Indian': '20'}
]

W tym systemie pierwszy wpis jest mylist[0]w klasycznej postaci zakończonej listą, a jego wartość to ('Apple', {'American':'16', 'Mexican':10, 'Chinese':5}). Możesz iterować całą listę w następujący sposób:

for (key, value) in mylist:  # unpacks to avoid tuple indexing
    if key == 'Apple':
        if 'American' in value:
            print(value['American'])

ale jeśli wiesz, że szukasz klucza „Apple”, dlaczego nie miałbyś zamiast tego po prostu użyć dyktowania?

Możesz wprowadzić dodatkowy poziom pośrednictwa, buforując listę kluczy, ale złożoność utrzymywania synchronizacji dwóch struktur danych nieuchronnie zwiększyłaby złożoność twojego kodu.


0

Dzięki tej małej funkcji zagłębianie się w słownik w kształcie drzewa staje się dość łatwe:

def dig(tree, path):
    for key in path.split("."):
        if isinstance(tree, dict) and tree.get(key):
            tree = tree[key]
        else:
            return None
    return tree

Teraz dig(mydict, "Apple.Mexican")zwraca 10, podczas gdy dig(mydict, "Grape")daje poddrzewo {'Arabian':'25','Indian':'20'}. Jeśli klucz nie jest zawarty w słowniku, digzwracaNone .

Zauważ, że możesz łatwo zmienić (lub nawet sparametryzować) znak separatora z „.” do „/”, „|” itp.

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.