for k, v in d.iteritems():
if type(v) is dict:
for t, c in v.iteritems():
print "{0} : {1}".format(t, c)
Saya mencoba mengulang melalui kamus dan mencetak semua pasangan nilai kunci yang nilainya bukan kamus bersarang. Jika nilainya adalah kamus, saya ingin membacanya dan mencetak pasangan nilai kuncinya ... dll. Ada bantuan?
EDIT
Bagaimana dengan ini? Itu masih hanya mencetak satu hal.
def printDict(d):
for k, v in d.iteritems():
if type(v) is dict:
printDict(v)
else:
print "{0} : {1}".format(k, v)
Kasus Uji Penuh
Kamus:
{u'xml': {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'},
u'port': u'11'}}
Hasil:
xml : {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'}, u'port': u'11'}
python
dictionary
Takkun
sumber
sumber
dict
sebagai nama variabel. Jangan pernah melakukan ini (inilah mengapa gagal).Jawaban:
Seperti yang dikatakan oleh Niklas, Anda memerlukan rekursi, yaitu Anda ingin menentukan fungsi untuk mencetak dict Anda, dan jika nilainya adalah dict, Anda ingin memanggil fungsi cetak Anda menggunakan dict baru ini.
Sesuatu seperti :
sumber
Ada potensi masalah jika Anda menulis implementasi rekursif Anda sendiri atau yang setara berulang dengan stack. Lihat contoh ini:
Dalam pengertian normal, kamus bersarang akan menjadi pohon n-nary seperti struktur data. Tetapi definisi tersebut tidak mengecualikan kemungkinan tepi silang atau bahkan tepi belakang (dengan demikian bukan lagi pohon). Misalnya, di sini key2.2 memegang kamus dari key1 , key2.3 menunjuk ke seluruh kamus (tepi belakang / siklus). Ketika ada back edge (siklus), stack / rekursi akan berjalan tanpa batas.
Jika Anda mencetak kamus ini dengan implementasi ini dari Scharron
Anda akan melihat kesalahan ini:
Hal yang sama berlaku untuk implementasi dari senderle .
Demikian pula, Anda mendapatkan loop tak terbatas dengan implementasi ini dari Fred Foo :
Namun, Python sebenarnya mendeteksi siklus dalam kamus bersarang:
"{...}" adalah tempat sebuah siklus terdeteksi.
Seperti yang diminta oleh Moondra, ini adalah cara untuk menghindari siklus (DFS):
sumber
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())
sebagaid.items()
mengembalikan tampilan, bukan daftar, dan gunakanv.items()
sebagai gantiv.iteritems()
Karena a
dict
iterable, Anda bisa menerapkan rumus iterable container bersarang klasik untuk masalah ini dengan hanya beberapa perubahan kecil. Ini adalah versi Python 2 (lihat di bawah untuk 3):Uji:
Dalam Python 2, Ini mungkin menjadi mungkin untuk membuat kustom
Mapping
yang memenuhi syarat sebagaiMapping
tetapi tidak mengandungiteritems
, dalam hal ini akan gagal. Dokumen tidak menunjukkan bahwaiteritems
diperlukan untuk aMapping
; di sisi lain, sumber memberikanMapping
tipeiteritems
metode. Jadi untuk customMappings
, mewarisi daricollections.Mapping
secara eksplisit untuk berjaga-jaga.Di Python 3, ada sejumlah perbaikan yang harus dilakukan. Pada Python 3.3, kelas dasar abstrak tinggal
collections.abc
. Mereka tetap adacollections
untuk kompatibilitas mundur, tetapi lebih baik memiliki kelas dasar abstrak kita bersama dalam satu namespace. Jadi ini mengimporabc
daricollections
. Python 3.3 juga menambahkanyield from
, yang dirancang hanya untuk situasi semacam ini. Ini bukan gula sintaksis kosong; ini dapat menghasilkan kode yang lebih cepat dan interaksi yang lebih masuk akal dengan coroutine .sumber
isinstance(item, collections.Iterable)
tidak ada jaminan untukhasattr(item, "iteritems")
. Memeriksacollections.Mapping
lebih baik.Iterable
akan membuat solusi ini lebih digeneralisasi, melupakan bahwa, jelas, iterable tidak harus begituiteritems
.yield from
sintaks baru .Solusi iteratif alternatif:
sumber
list
) dengandeque
atau bahkan antrian prioritas.Versi yang sedikit berbeda saya tulis yang melacak kunci di sepanjang jalan menuju ke sana
Pada data Anda, itu akan dicetak
Ini juga mudah untuk memodifikasinya untuk melacak awalan sebagai tupel kunci daripada string jika Anda membutuhkannya seperti itu.
sumber
Inilah cara pythonic untuk melakukannya. Fungsi ini akan memungkinkan Anda untuk melakukan loop melalui key-value pair di semua level. Itu tidak menyimpan semuanya ke memori melainkan berjalan melalui dict saat Anda mengulanginya
Cetakan
sumber
Solusi alternatif untuk bekerja dengan daftar berdasarkan solusi Scharron
sumber
Solusi berulang sebagai alternatif:
sumber
O(depth)
untuk solusi rekursif. Hal yang sama berlaku untuk versi ini, jika saya berpikir dengan benar).iters
sebagai tumpukan eksplisit, jadi konsumsi memori Big-O sama, atau saya kehilangan sesuatu?Saya menggunakan kode berikut untuk mencetak semua nilai kamus bersarang, dengan mempertimbangkan di mana nilainya bisa berupa daftar yang berisi kamus. Ini berguna bagi saya saat mengurai file JSON ke dalam kamus dan perlu memeriksa dengan cepat apakah ada nilainya
None
.Keluaran:
sumber
Berikut adalah versi modifikasi dari jawaban Fred Foo untuk Python 2. Dalam respons asli, hanya tingkat bersarang yang paling dalam yang dihasilkan. Jika Anda mengeluarkan kunci sebagai daftar, Anda dapat menyimpan kunci untuk semua level, meskipun untuk mereferensikannya Anda perlu merujuk daftar daftar.
Berikut fungsinya:
Untuk mereferensikan kunci:
untuk kamus tiga tingkat.
Anda perlu mengetahui jumlah level sebelum mengakses beberapa kunci dan jumlah level harus konstan (dimungkinkan untuk menambahkan sedikit skrip untuk memeriksa jumlah level bersarang saat mengulang nilai, tetapi saya belum belum melihat ini).
sumber
Saya menemukan pendekatan ini sedikit lebih fleksibel, di sini Anda hanya menyediakan fungsi generator yang memancarkan kunci, pasangan nilai dan dapat dengan mudah diperluas untuk juga mengulang daftar.
Kemudian Anda dapat menulis
myprint
fungsi Anda sendiri , lalu mencetak pasangan nilai kunci tersebut.Sebuah tes:
Keluaran:
Saya menguji ini pada Python 3.6.
sumber
Jawaban ini hanya berfungsi untuk 2 level sub-kamus. Untuk lebih lanjut coba ini:
sumber