programing

중첩된 모든 사전 값을 반복하시겠습니까?

mytipbox 2023. 6. 7. 23:47
반응형

중첩된 모든 사전 값을 반복하시겠습니까?

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

사전을 루프하여 값이 중첩된 사전이 아닌 모든 키 값 쌍을 인쇄하려고 합니다.값이 사전인 경우에는 사전에 들어가 키 값 쌍을 인쇄합니다.도와드릴까요?

편집

이건 어때?여전히 한 가지만 출력합니다.

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'}

Niklas가 말했듯이, 당신은 재귀가 필요합니다. 즉, 당신은 당신의 딕트를 인쇄하기 위한 함수를 정의하고, 만약 그 값이 딕트라면, 당신은 이 새로운 딕트를 사용하여 당신의 프린트 함수를 호출하기를 원합니다.

다음과 같은 것:

def myprint(d):
    for k, v in d.items():
        if isinstance(v, dict):
            myprint(v)
        else:
            print("{0} : {1}".format(k, v))

스택을 사용하여 자신만의 재귀적 구현이나 반복적으로 동일한 구현을 작성하는 경우 잠재적인 문제가 발생할 수 있습니다.다음 예를 참조하십시오.

dic = {}
dic["key1"] = {}
dic["key1"]["key1.1"] = "value1"
dic["key2"]  = {}
dic["key2"]["key2.1"] = "value2"
dic["key2"]["key2.2"] = dic["key1"]
dic["key2"]["key2.3"] = dic

일반적인 의미에서, 중첩된 사전은 nary 트리와 같은 데이터 구조가 될 것입니다.그러나 그 정의는 교차 에지 또는 심지어 백 에지(따라서 더 이상 트리가 아님)의 가능성을 배제하지 않습니다.예를 들어, 여기 키2가 있습니다.2 키 1, 키 2.3 포인트에서 전체 사전(백 에지/사이클)까지 사전을 유지합니다.백 에지(사이클)가 있으면 스택/재귀가 무한 실행됩니다.

            root<-------back edge
          /      \           |
       _key1   __key2__      |
      /       /   \    \     |
 |->key1.1 key2.1 key2.2 key2.3
 |   /       |      |
 | value1  value2   |
 |                  | 
cross edge----------|

샤론의 이 구현으로 이 사전을 인쇄하면

def myprint(d):
    for k, v in d.items():
        if isinstance(v, dict):
            myprint(v)
        else:
            print "{0} : {1}".format(k, v)
            

다음 오류가 표시됩니다.

> RuntimeError: maximum recursion depth exceeded while calling a Python object

senderle의 구현도 마찬가지입니다.

마찬가지로 Fred Foo는 이 구현을 통해 무한 루프를 제공합니다.

def myprint(d):
    stack = list(d.items())
    while stack:
        k, v = stack.pop()
        if isinstance(v, dict):
            stack.extend(v.items())
        else:
            print("%s: %s" % (k, v))

그러나 Python은 실제로 중첩된 사전에서 주기를 감지합니다.

print dic
{'key2': {'key2.1': 'value2', 'key2.3': {...}, 
       'key2.2': {'key1.1': 'value1'}}, 'key1': {'key1.1': 'value1'}}

사이클이 감지되는 곳입니다.

문드라가 요청한 대로 사이클(DFS)을 피하는 방법입니다.

def myprint(d): 
    stack = list(d.items()) 
    visited = set() 
    while stack: 
        k, v = stack.pop() 
        if isinstance(v, dict): 
            if k not in visited: 
                stack.extend(v.items()) 
        else: 
            print("%s: %s" % (k, v)) 
        visited.add(k)

로 로.dict반복할 수 있습니다. 몇 가지 사소한 변경만으로 이 문제에 고전적인 중첩 컨테이너 반복 가능 공식을 적용할 수 있습니다.다음은 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에서는 사용자 지정을 생성할 수 있습니다.Mapping은 의자이있는격▁as의 자격이 있습니다.Mapping하지만 포함하지 않습니다.iteritems이 경우에는 실패할 것입니다.서류상으로는 그런 것이 없습니다iteritems에 합니다.Mapping반면에, 출처는 다음과 같습니다.Mappingiteritems방법.그래서 맞춤형으로Mappings에서물은에서 collections.Mapping만일의 경우를 대비하여 명시적으로

Python 3에서는 여러 가지 개선 사항이 있습니다. 3 클래스는 Python 3.3에서 됩니다.collections.abc그들은 남아 있습니다.collections이전 버전과의 호환성을 고려해야 하지만 추상 기본 클래스를 하나의 네임스페이스에 함께 사용하는 것이 더 좋습니다.그래서 이것은 수입합니다.abccollections또한 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

대체 반복 솔루션:

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))

내가 작성한 약간 다른 버전은 거기까지 가는 길에 키를 추적합니다.

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'

필요한 경우 접두사를 문자열이 아닌 키 튜플로 추적하도록 쉽게 수정할 수 있습니다.

여기 그것을 하는 부정적인 방법이 있습니다.이 기능을 사용하면 모든 수준에서 키-값 쌍을 반복 처리할 수 있습니다.전체를 메모리에 저장하는 것이 아니라 반복하면서 딕트를 통과합니다.

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

Sharron의 솔루션을 기반으로 한 목록 작업을 위한 대체 솔루션

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)

값이 사전을 포함하는 목록일 수 있는 위치를 고려하여 다음 코드를 사용하여 중첩된 사전의 모든 값을 인쇄합니다.이것은 JSON 파일을 사전으로 구문 분석할 때 유용했고 그 값 중 하나라도 빨리 확인해야 했습니다.None.

    d = {
            "user": 10,
            "time": "2017-03-15T14:02:49.301000",
            "metadata": [
                {"foo": "bar"},
                "some_string"
            ]
        }


    def print_nested(d):
        if isinstance(d, dict):
            for k, v in d.items():
                print_nested(v)
        elif hasattr(d, '__iter__') and not isinstance(d, str):
            for item in d:
                print_nested(item)
        elif isinstance(d, str):
            print(d)

        else:
            print(d)

    print_nested(d)

출력:

    10
    2017-03-15T14:02:49.301000
    bar
    some_string

당신의 질문은 이미 잘 답변되었지만, 저는 사용하는 것을 추천합니다.isinstance(d, collections.Mapping)isinstance(d, dict)에 효과가 있습니다.dict(),collections.OrderedDict(),그리고.collections.UserDict().

일반적으로 올바른 버전은 다음과 같습니다.

def myprint(d):
    for k, v in d.items():
        if isinstance(v, collections.Mapping):
            myprint(v)
        else:
            print("{0} : {1}".format(k, v))

대안으로서 반복적인 솔루션:

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

저는 이 접근 방식이 좀 더 유연하다고 생각합니다. 여기서는 키, 값 쌍을 내보내고 목록 위에서 반복하도록 쉽게 확장할 수 있는 제너레이터 기능을 제공합니다.

def traverse(value, key=None):
    if isinstance(value, dict):
        for k, v in value.items():
            yield from traverse(v, k)
    else:
        yield key, value

그러면 당신은 당신 자신의 것을 쓸 수 있습니다.myprint키 값 쌍을 인쇄할 수 있습니다.

def myprint(d):
    for k, v in traverse(d):
        print(f"{k} : {v}")

테스트:

myprint({
    'xml': {
        'config': {
            'portstatus': {
                'status': 'good',
            },
            'target': '1',
        },
        'port': '11',
    },
})

출력:

status : good
target : 1
port : 11

저는 이것을 Python 3.6에서 테스트했습니다.

여기 Fred Foo의 파이썬 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단계 사전을 위한

여러 키에 액세스하려면 먼저 레벨 수를 알아야 하며 레벨 수는 일정해야 합니다(값을 반복할 때 중첩 레벨 수를 확인하기 위해 작은 스크립트를 추가할 수도 있지만 아직 이에 대해서는 살펴보지 않았습니다).

isinstance() 및 수율 함수를 사용하여 반복되는 중첩된 사전입니다.**isinstance는 지정된 입력을 반환하는 함수이며 아래와 같이 참조가 true이고, dict가 true인 경우에는 false이므로 반복됩니다.** 수율은 로컬 변수의 상태를 파괴하지 않고 함수에서 반환하는 데 사용되며 함수가 호출되면 마지막 수율 문에서 실행이 시작됩니다.수율 키워드를 포함하는 함수를 생성기라고 합니다.

students= {'emp1': {'name': 'Bob', 'job': 'Mgr'},
     'emp2': {'name': 'Kim', 'job': 'Dev','emp3': {'namee': 'Saam', 'j0ob': 'Deev'}},
     'emp4': {'name': 'Sam', 'job': 'Dev'}}
def nested_dict_pairs_iterator(dict_obj):
     for key, value in dict_obj.items():
        # Check if value is of dict type
        if isinstance(value, dict):
            # If value is dict then iterate over all its values
            for pair in  nested_dict_pairs_iterator(value):
                yield (key, *pair)
        else:
            # If value is not dict type then yield the value
            yield (key, value)
for pair in nested_dict_pairs_iterator(students):
    print(pair)

기성 솔루션의 경우 설치 명령어

pip install ndicts

스크립트에서 NestedDict 가져오기

from ndicts.ndicts import NestedDict

초기화

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

nd = NestedDict(dictionary)

반복

for key, value in nd.items():
    print(key, value)

@Sharron의 원래 솔루션은 아름답고 단순하지만 목록을 잘 처리할 수 없습니다.

def myprint(d):
    for k, v in d.items():
        if isinstance(v, dict):
            myprint(v)
        else:
            print("{0} : {1}".format(k, v))

따라서 이 코드는 요소의 목록을 처리하기 위해 다음과 같이 약간 수정할 수 있습니다.

def myprint(d):
    for k, v in d.items():
        if isinstance(v, dict):
            myprint(v)
        elif isinstance(v, list):
            for i in v:
                myprint(i)
        else:
            print("{0} : {1}".format(k, v))

이러한 답변은 하위 사전의 두 단계에서만 사용할 수 있습니다.자세한 내용은 다음을 참조하십시오.

nested_dict = {'dictA': {'key_1': 'value_1', 'key_1A': 'value_1A','key_1Asub1': {'Asub1': 'Asub1_val', 'sub_subA1': {'sub_subA1_key':'sub_subA1_val'}}},
                'dictB': {'key_2': 'value_2'},
                1: {'key_3': 'value_3', 'key_3A': 'value_3A'}}

def print_dict(dictionary):
    dictionary_array = [dictionary]
    for sub_dictionary in dictionary_array:
        if type(sub_dictionary) is dict:
            for key, value in sub_dictionary.items():
                print("key=", key)
                print("value", value)
                if type(value) is dict:
                    dictionary_array.append(value)



print_dict(nested_dict)

사전 이해를 통해 재귀적으로 인쇄할 수 있습니다.

def print_key_pairs(d):
    {k: print_key_pairs(v) if isinstance(v, dict) else print(f'{k}: {v}') for k, v in d.items()}

테스트 사례의 출력은 다음과 같습니다.

>>> print_key_pairs({u'xml': {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'}, u'port': u'11'}})
status: good
target: 1
port: 11

각 키와 값의 튜플을 반환하고 키에 전체 경로가 포함됩니다.

from typing import Mapping, Tuple, Iterator

def traverse_dict(nested: Mapping, parent_key="", keys_to_not_traverse_further=tuple()) -> Iterator[Tuple[str, str]]:
    """Each key is joined with it's parent using dot as a separator.

    Once a `parent_key` matches `keys_to_not_traverse_further` 
   it will no longer find its child dicts.
   """
    for key, value in nested.items():
        if isinstance(value, abc.Mapping) and key not in keys_to_not_traverse_further:
            yield from traverse_dict(value, f"{parent_key}.{key}", keys_to_not_traverse_further)
        else:
            yield f"{parent_key}.{key}", value

테스트해 보겠습니다.

my_dict = {
    "isbn": "123-456-222",
    "author": {"lastname": "Doe", "firstname": "Jane"},
    "editor": {"lastname": "Smith", "firstname": "Jane"},
    "title": "The Ultimate Database Study Guide",
    "category": ["Non-Fiction", "Technology"],
    "first": {
        "second": {"third": {"fourth": {"blah": "yadda"}}},
        "fifth": {"sixth": "seventh"},
    },
}
for k, v in traverse_dict(my_dict):
    print(k, v)

돌아온다

.isbn 123-456-222
.author.lastname Doe
.author.firstname Jane
.editor.lastname Smith
.editor.firstname Jane
.title The Ultimate Database Study Guide
.category ['Non-Fiction', 'Technology']
.first.second.third.fourth.blah yadda
.first.fifth.sixth seventh

만약 당신이 이 경우에 몇몇 아이들이 예를 들어 이름을 받아쓰는 것에 신경 쓰지 않는다면, 그것을 사용하세요.keys_to_not_traverse_further

for k, v in traverse_dict(my_dict, parent_key="", keys_to_not_traverse_further=("author","editor")):
    print(k, v)

돌아온다

.isbn 123-456-222
.author {'lastname': 'Doe', 'firstname': 'Jane'}
.editor {'lastname': 'Smith', 'firstname': 'Jane'}
.title The Ultimate Database Study Guide
.category ['Non-Fiction', 'Technology']
.first.second.third.fourth.blah yadda
.first.fifth.sixth seventh

언급URL : https://stackoverflow.com/questions/10756427/loop-through-all-nested-dictionary-values

반응형