152
for k, v in d.iteritems():
    if type(v) is dict:
        for t, c in v.iteritems():
            print "{0} : {1}".format(t, c)

辞書をループして、値がネストされた辞書ではないすべてのキーと値のペアを出力しようとしています。値が辞書の場合は、その値にアクセスして、そのキーと値のペアを出力したい...など。何か助けはありますか?

編集

これはどう?まだ1つしか印刷されません。

def printDict(d):
    for k, v in d.iteritems():
        if type(v) is dict:
            printDict(v)
        else:
            print "{0} : {1}".format(k, v)

完全なテスト ケース

辞書:

{u'xml': {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'},
      u'port': u'11'}}

結果:

xml : {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'}, u'port': u'11'}
4

15 に答える 15

199

Niklasが言ったように、再帰が必要です。つまり、dictを印刷する関数を定義し、値がdictの場合は、この新しいdictを使用してprint関数を呼び出します。

何かのようなもの :

def myprint(d):
    for k, v in d.items():
        if isinstance(v, dict):
            myprint(v)
        else:
            print("{0} : {1}".format(k, v))
于 2012-05-25T14:47:57.220 に答える
43

adictは iterable であるため、2、3 の小さな変更を加えるだけで、従来のネストされたコンテナの iterable 式をこの問題に適用できます。これは Python 2 バージョンです (3 については以下を参照)。

import collections
def nested_dict_iter(nested):
    for key, value in nested.iteritems():
        if isinstance(value, collections.Mapping):
            for inner_key, inner_value in nested_dict_iter(value):
                yield inner_key, inner_value
        else:
            yield key, value

テスト:

list(nested_dict_iter({'a':{'b':{'c':1, 'd':2}, 
                            'e':{'f':3, 'g':4}}, 
                       'h':{'i':5, 'j':6}}))
# output: [('g', 4), ('f', 3), ('c', 1), ('d', 2), ('i', 5), ('j', 6)]

Python 2 では、として適格であるが を含まないカスタムを作成できる可能があります。その場合、これは失敗します。ドキュメントは、それが必要であることを示していません; 一方、ソースは型にメソッドを提供します。したがって、 customの場合、念のため明示的に継承します。MappingMappingiteritemsiteritemsMappingMappingiteritemsMappingscollections.Mapping

Python 3 では、多くの改善が必要です。Python 3.3 以降、抽象基底クラスはcollections.abc. これらも下位互換性のために残っていcollectionsますが、抽象基本クラスを 1 つの名前空間にまとめたほうがよいでしょう。したがって、これはabcからインポートされcollectionsます。Python 3.3 ではyield from、まさにこのような状況向けに設計された も追加されています。これは空のシンタックス シュガーではありません。これにより、コードが高速になり、コルーチンとのより賢明なやり取りが可能になります。

from collections import abc
def nested_dict_iter(nested):
    for key, value in nested.items():
        if isinstance(value, abc.Mapping):
            yield from nested_dict_iter(value)
        else:
            yield key, value
于 2012-05-25T14:52:40.330 に答える
30

代替の反復ソリューション:

def myprint(d):
    stack = d.items()
    while stack:
        k, v = stack.pop()
        if isinstance(v, dict):
            stack.extend(v.iteritems())
        else:
            print("%s: %s" % (k, v))
于 2012-05-25T15:22:21.180 に答える
17

そこにたどり着くまでの途中でキーを追跡する、私が書いたわずかに異なるバージョン

def print_dict(v, prefix=''):
    if isinstance(v, dict):
        for k, v2 in v.items():
            p2 = "{}['{}']".format(prefix, k)
            print_dict(v2, p2)
    elif isinstance(v, list):
        for i, v2 in enumerate(v):
            p2 = "{}[{}]".format(prefix, i)
            print_dict(v2, p2)
    else:
        print('{} = {}'.format(prefix, repr(v)))

あなたのデータでは、それは印刷されます

data['xml']['config']['portstatus']['status'] = u'good'
data['xml']['config']['target'] = u'1'
data['xml']['port'] = u'11'

必要に応じて、プレフィックスを文字列ではなくキーのタプルとして追跡するように変更することも簡単です。

于 2016-02-13T12:55:58.920 に答える
8

ここにそれを行うpythonicの方法があります。この関数を使用すると、すべてのレベルでキーと値のペアをループできます。全体をメモリに保存するのではなく、ループするときにdictをウォークスルーします

def recursive_items(dictionary):
    for key, value in dictionary.items():
        if type(value) is dict:
            yield (key, value)
            yield from recursive_items(value)
        else:
            yield (key, value)

a = {'a': {1: {1: 2, 3: 4}, 2: {5: 6}}}

for key, value in recursive_items(a):
    print(key, value)

版画

a {1: {1: 2, 3: 4}, 2: {5: 6}}
1 {1: 2, 3: 4}
1 2
3 4
2 {5: 6}
5 6
于 2016-08-30T18:03:14.227 に答える
7

Scharron のソリューションに基づくリストを操作するための代替ソリューション

def myprint(d):
    my_list = d.iteritems() if isinstance(d, dict) else enumerate(d)

    for k, v in my_list:
        if isinstance(v, dict) or isinstance(v, list):
            myprint(v)
        else:
            print u"{0} : {1}".format(k, v)
于 2015-09-30T21:37:11.953 に答える
2

代替案としての反復ソリューション:

def traverse_nested_dict(d):
    iters = [d.iteritems()]

    while iters:
        it = iters.pop()
        try:
            k, v = it.next()
        except StopIteration:
            continue

        iters.append(it)

        if isinstance(v, dict):
            iters.append(v.iteritems())
        else:
            yield k, v


d = {"a": 1, "b": 2, "c": {"d": 3, "e": {"f": 4}}}
for k, v in traverse_nested_dict(d):
    print k, v
于 2012-05-25T15:17:11.400 に答える
1

Here's a modified version of Fred Foo's answer for Python 2. 元の応答では、ネストの最も深いレベルのみが出力されます。キーをリストとして出力すると、すべてのレベルのキーを保持できますが、キーを参照するにはリストのリストを参照する必要があります。

関数は次のとおりです。

def NestIter(nested):
    for key, value in nested.iteritems():
        if isinstance(value, collections.Mapping):
            for inner_key, inner_value in NestIter(value):
                yield [key, inner_key], inner_value
        else:
            yield [key],value

キーを参照するには:

for keys, vals in mynested: 
    print(mynested[keys[0]][keys[1][0]][keys[1][1][0]])

3 レベルの辞書の場合。

複数のキーにアクセスする前にレベルの数を知る必要があり、レベルの数は一定である必要があります (値を反復処理するときに、ネストされたレベルの数をチェックするスクリプトを少し追加することは可能かもしれませんが、私はまだ行っていません)まだこれを見た)。

于 2016-05-26T14:19:53.027 に答える