모든 중첩 된 사전 값을 반복 하시겠습니까?
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가 말했듯이 재귀가 필요합니다. 즉, dict를 인쇄 할 함수를 정의하고 값이 dict 인 경우이 새로운 dict를 사용하여 인쇄 함수를 호출하고 싶습니다.
다음과 같은 것 :
def myprint(d):
for k, v in d.iteritems():
if isinstance(v, dict):
myprint(v)
else:
print "{0} : {1}".format(k, v)
또는 Python 3 이상 :
def myprint(d):
for k, v in d.items():
if isinstance(v, dict):
myprint(v)
else:
print("{0} : {1}".format(k, v))
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)]
파이썬 2에서, 수있는 user-정의 만들 수있을 Mapping
자격을 것을와 Mapping
하지만이 포함되지 않은 iteritems
,이 경우이 실패합니다. 문서는 iteritems
필요한 것을 작성하는 방법 Mapping
; 반면 소스 는 Mapping
유형에 iteritems
메소드를 제공 합니다 . 따라서 커스텀의 경우 경우 에 대비 Mappings
하여 collections.Mapping
명시 적으로 상속하십시오 .
Python 3에는 몇 가지 개선해야 할 사항이 있습니다. Python 3.3부터 추상 기본 클래스는 collections.abc
. collections
이전 버전과의 사용을 위해 그대로 유지 스페이스 추상 기본 클래스를 하나의 네임 스페이스에 사용하는 것이 더 좋습니다. 이 수입 그래서 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
대체 반복 솔루션 :
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))
있다 잠재적 인 문제 당신이 당신의 자신의 재귀 구현 또는 스택 반복 동등한를 작성하는 경우는. 이 예를 참조하십시오.
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
동일한 의미에서 중첩 사전은 데이터 구조와 같은 n-nary 트리가됩니다. 정의 그러나 는 교차 가장자리 또는 심지어 뒤쪽 가장자리의 가능성을 배제하지 않습니다 (따라서 더 이상 나무가 아닙니다). 예를 들어, 여기 key2.2 에서 사전에 보유하고 키 1 , key2.3의 전체 사전에 점 (후면 가장자리 / 사이클). 백 엣지 (사이클)가 있으면 스택 / 재귀가 무한히 실행됩니다.
root<-------back edge
/ \ |
_key1 __key2__ |
/ / \ \ |
|->key1.1 key2.1 key2.2 key2.3
| / | |
| value1 value2 |
| |
cross edge----------|
Scharron 에서이 구현 으로이 사전을 인쇄하면
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'}}
"{...}" 는주기가 감지되는 곳입니다.
Moondra 가 요청 한대로 이주기 (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)
거기에 도착하는 길을 따라 키를 추적하는 약간의 다른 버전
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'
필요한 경우라면이 아닌 키의 튜플로 접두사를 추적하도록 수정하는 것도 있습니다.
여기에 비단뱀적인 방법이 있습니다. 이 함수를 사용하면 모든 수준에서 키-값 쌍을 반복 할 수 있습니다. 그것은 모든 것을 메모리에 저장하지 않고 반복하는 동안 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
대안으로 반복 솔루션 :
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
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)
다음은 Python 2에 대한 Fred Foo의 답변의 수정 된 버전입니다. 원래 응답에서는 가장 깊은 수준의 중첩 만 출력됩니다. 키를 목록으로 출력하면 모든 수준의 키를 유지할 수 있지만 참조하려면 목록 목록을 참조해야합니다.
기능은 다음과 같습니다.
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 단계 사전의 경우.
여러 키에 액세스하기 전에 레벨 수를 알아야하며 레벨 수는 일정해야합니다 (값을 반복 할 때 중첩 레벨 수를 확인하기 위해 약간의 스크립트를 추가 할 수 있지만 아직 확인하지 못했습니다). 아직 봤다).
이 접근 방식이 좀 더 유연하다는 것을 알았습니다. 여기서 키, 값 쌍을 내보내고 목록을 반복하도록 쉽게 확장 할 수있는 생성기 함수 만 제공합니다.
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에서 테스트했습니다.
다음 코드를 사용하여 값이 사전을 포함하는 목록이 될 수있는 위치를 고려하여 중첩 된 사전의 모든 값을 인쇄합니다. 이것은 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
참고 URL : https://stackoverflow.com/questions/10756427/loop-through-all-nested-dictionary-values
'IT' 카테고리의 다른 글
명령 줄 도구가 설치되어 있는지 확인하는 방법 (0) | 2020.09.11 |
---|---|
1.0이 아닌 열거 형 값에 0.0을 할당 할 수있는 이유 (0) | 2020.09.11 |
JavaScript를 통해 사용자 로컬 LAN IP 주소를 얻을 수 있습니까? (0) | 2020.09.11 |
기능의 설명 (0) | 2020.09.11 |
왜 빌드 후 단계 (xcopy)가 TeamCity 빌드에서 코드 2와 함께 종료합니까? (0) | 2020.09.11 |