for k, v in d.iteritems():
if type(v) is dict:
for t, c in v.iteritems():
print "{0} : {1}".format(t, c)
Próbuję przejrzeć słownik i wydrukować wszystkie pary klucz-wartość, w przypadku których wartość nie jest zagnieżdżonym słownikiem. Jeśli wartość jest słownikiem, chcę do niego wejść i wydrukować pary klucz-wartość ... itd. Jakaś pomoc?
EDYTOWAĆ
Co powiesz na to? Nadal drukuje tylko jedną rzecz.
def printDict(d):
for k, v in d.iteritems():
if type(v) is dict:
printDict(v)
else:
print "{0} : {1}".format(k, v)
Pełny przypadek testowy
Słownik:
{u'xml': {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'},
u'port': u'11'}}
Wynik:
xml : {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'}, u'port': u'11'}
python
dictionary
Takkun
źródło
źródło
dict
jako nazwy zmiennej. Nigdy tego nie rób (dlatego się nie udaje).Odpowiedzi:
Jak powiedział Niklas, potrzebujesz rekurencji, tj. Chcesz zdefiniować funkcję, która wydrukuje twój dykt, a jeśli wartością jest dict, chcesz wywołać swoją funkcję print używając tego nowego dyktu.
Coś jak :
źródło
Istnieją potencjalne problemy, jeśli napiszesz własną implementację rekurencyjną lub iteracyjny odpowiednik ze stosem. Zobacz ten przykład:
W normalnym sensie słownik zagnieżdżony będzie n-arowym drzewem, podobnym do struktury danych. Ale definicja nie wyklucza możliwości krawędzi poprzecznej lub nawet tylnej krawędzi (a zatem nie jest już drzewem). Na przykład, o key2.2 posiada słownika z key1 , key2.3 wskazuje na całej tylnej krawędzi (słowniku / stopień). Kiedy występuje tylna krawędź (cykl), stos / rekursja będzie działać w nieskończoność.
Jeśli drukujesz ten słownik z tą implementacją firmy Scharron
Zobaczysz ten błąd:
To samo dotyczy implementacji od senderle .
Podobnie, dzięki tej implementacji Freda Foo otrzymujesz nieskończoną pętlę :
Jednak Python faktycznie wykrywa cykle w zagnieżdżonym słowniku:
„{...}” to miejsce, w którym wykrywany jest cykl.
Zgodnie z życzeniem firmy Moondra jest to sposób na uniknięcie cykli (DFS):
źródło
def myprint(d): stack = d.items() visited = set() while stack: k, v = stack.pop() if isinstance(v, dict): if k not in visited: stack.extend(v.iteritems()) else: print("%s: %s" % (k, v)) visited.add(k)
list(d.items())
asd.items()
zwraca widok, a nie listę, i użyjv.items()
zamiastv.iteritems()
Ponieważ a
dict
jest iterowalny, możesz zastosować do tego problemu klasyczną iterowalną formułę zagnieżdżonego kontenera, dokonując tylko kilku drobnych zmian. Oto wersja Pythona 2 (patrz poniżej 3):Test:
W Pythonie 2 może być możliwe utworzenie niestandardowego,
Mapping
który kwalifikuje się jako a,Mapping
ale nie zawieraiteritems
, w takim przypadku zakończy się to niepowodzeniem. Dokumenty nie wskazują, żeiteritems
jest to wymagane dlaMapping
; z drugiej strony źródło podajeMapping
typomiteritems
metodę. Tak więc w przypadku niestandardowychMappings
dziedzicz zcollections.Mapping
wyraźnie na wszelki wypadek.W Pythonie 3 jest wiele ulepszeń, które należy wprowadzić. Począwszy od Pythona 3.3, istnieją abstrakcyjne klasy bazowe
collections.abc
. Pozostają onecollections
również w celu zachowania kompatybilności wstecznej, ale przyjemniej jest mieć nasze abstrakcyjne klasy bazowe razem w jednej przestrzeni nazw. Więc to importujeabc
zcollections
. Python 3.3 również dodajeyield from
, który jest przeznaczony tylko do tego rodzaju sytuacji. To nie jest pusty cukier syntaktyczny; może to prowadzić do szybszego kodu i bardziej sensownych interakcji z programami .źródło
isinstance(item, collections.Iterable)
nie ma gwarancjihasattr(item, "iteritems")
. Sprawdzaniecollections.Mapping
jest lepsze.Iterable
uczyniłoby to rozwiązanie bardziej uogólnionym, zapominając, że oczywiście iterowalne niekoniecznie mająiteritems
.yield from
składni.Alternatywne rozwiązanie iteracyjne:
źródło
list
)deque
kolejką lub nawet kolejką priorytetową.Nieco inna wersja, którą napisałem, która śledzi klucze po drodze, aby się tam dostać
Na twoich danych zostanie wydrukowany
Łatwo jest go również zmodyfikować, aby śledzić prefiks jako krotkę kluczy, a nie ciąg znaków, jeśli potrzebujesz tego w ten sposób.
źródło
Oto pythonowy sposób na zrobienie tego. Ta funkcja umożliwia przechodzenie przez parę klucz-wartość na wszystkich poziomach. Nie zapisuje całości w pamięci, ale raczej przechodzi przez dyktowanie, gdy przechodzisz przez pętlę
Wydruki
źródło
Alternatywne rozwiązanie do pracy z listami opartymi na rozwiązaniu Scharron
źródło
Rozwiązanie iteracyjne jako alternatywa:
źródło
O(depth)
rozwiązania rekurencyjnego. To samo dotyczy tej wersji, jeśli dobrze myślę).iters
jako jawnego stosu, więc zużycie pamięci Big-O jest takie samo, czy czegoś mi brakuje?Używam następującego kodu, aby wydrukować wszystkie wartości zagnieżdżonego słownika, biorąc pod uwagę, gdzie wartością może być lista zawierająca słowniki. Było to przydatne podczas analizowania pliku JSON w słowniku i konieczności szybkiego sprawdzenia, czy któraś z jego wartości jest
None
.Wynik:
źródło
Oto zmodyfikowana wersja odpowiedzi Freda Foo dla Pythona 2. W oryginalnej odpowiedzi wyprowadzany jest tylko najgłębszy poziom zagnieżdżenia. Jeśli wyprowadzasz klucze jako listy, możesz zachować klucze na wszystkich poziomach, chociaż aby się do nich odwołać, musisz odwołać się do listy list.
Oto funkcja:
Aby odwołać się do kluczy:
dla słownika trzypoziomowego.
Musisz znać liczbę poziomów zanim uzyskasz dostęp do wielu kluczy, a liczba poziomów powinna być stała (może być możliwe dodanie małego skryptu, aby sprawdzić liczbę poziomów zagnieżdżenia podczas iteracji przez wartości, ale nie jeszcze spojrzał na to).
źródło
Uważam, że to podejście jest nieco bardziej elastyczne, tutaj po prostu zapewniasz funkcję generatora, która emituje pary kluczy i wartości i może być łatwo rozszerzona, aby również iterować po listach.
Następnie możesz napisać własną
myprint
funkcję, a następnie wydrukować te pary klucz-wartość.Test:
Wynik:
Przetestowałem to na Pythonie 3.6.
źródło
Te odpowiedzi działają tylko dla 2 poziomów słowników podrzędnych. Aby uzyskać więcej, spróbuj tego:
źródło