Tak*_*kun 93 python dictionary
for k, v in d.iteritems():
if type(v) is dict:
for t, c in v.iteritems():
print "{0} : {1}".format(t, c)
Run Code Online (Sandbox Code Playgroud)
我正在尝试遍历字典并打印出值不是嵌套字典的所有键值对.如果值是字典,我想进入它并打印出其键值对...等.有帮助吗?
编辑
这个怎么样?它仍然只打印一件事.
def printDict(d):
for k, v in d.iteritems():
if type(v) is dict:
printDict(v)
else:
print "{0} : {1}".format(k, v)
Run Code Online (Sandbox Code Playgroud)
完整测试案例
字典:
{u'xml': {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'},
u'port': u'11'}}
Run Code Online (Sandbox Code Playgroud)
结果:
xml : {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'}, u'port': u'11'}
Run Code Online (Sandbox Code Playgroud)
Sch*_*ron 124
正如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)
Run Code Online (Sandbox Code Playgroud)
或者对于Python 3以上版本:
def myprint(d):
for k, v in d.items():
if isinstance(v, dict):
myprint(v)
else:
print("{0} : {1}".format(k, v))
Run Code Online (Sandbox Code Playgroud)
sen*_*rle 28
由于a 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
Run Code Online (Sandbox Code Playgroud)
测试:
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)]
Run Code Online (Sandbox Code Playgroud)
在Python 2,这或许可以创建自定义的Mapping
有资格的Mapping
,但不包含iteritems
,在这种情况下,这将失败.文档并未表明iteritems
a是必需的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
Run Code Online (Sandbox Code Playgroud)
ten*_*ngr 25
如果您编写自己的递归实现或迭代等效的堆栈,则存在潜在的问题.看这个例子:
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
Run Code Online (Sandbox Code Playgroud)
在通常意义上,嵌套字典将是一个像数据结构一样的n-nary树.但该定义并未排除交叉边缘甚至后边缘(因此不再是树)的可能性.例如,这里key2.2从key1保持字典,key2.3指向整个字典(后边缘/循环).当存在后沿(循环)时,堆栈/递归将无限运行.
root<-------back edge
/ \ |
_key1 __key2__ |
/ / \ \ |
|->key1.1 key2.1 key2.2 key2.3
| / | |
| value1 value2 |
| |
cross edge----------|
Run Code Online (Sandbox Code Playgroud)
如果您使用Scharron的此实现打印此字典
def myprint(d):
for k, v in d.items():
if isinstance(v, dict):
myprint(v)
else:
print "{0} : {1}".format(k, v)
Run Code Online (Sandbox Code Playgroud)
你会看到这个错误:
RuntimeError: maximum recursion depth exceeded while calling a Python object
Run Code Online (Sandbox Code Playgroud)
来自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))
Run Code Online (Sandbox Code Playgroud)
但是,Python实际上会检测嵌套字典中的循环:
print dic
{'key2': {'key2.1': 'value2', 'key2.3': {...},
'key2.2': {'key1.1': 'value1'}}, 'key1': {'key1.1': 'value1'}}
Run Code Online (Sandbox Code Playgroud)
"{...}"是检测到循环的地方.
根据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)
Run Code Online (Sandbox Code Playgroud)
Fre*_*Foo 23
替代迭代解决方案:
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))
Run Code Online (Sandbox Code Playgroud)
使用基于 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)
Run Code Online (Sandbox Code Playgroud)
我编写的版本略有不同,可以跟踪到达目的地的密钥
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)))
Run Code Online (Sandbox Code Playgroud)
在您的数据上,它将打印出来
data['xml']['config']['portstatus']['status'] = u'good'
data['xml']['config']['target'] = u'1'
data['xml']['port'] = u'11'
Run Code Online (Sandbox Code Playgroud)
它也很容易修改它来跟踪前缀作为键的元组而不是字符串,如果你需要它那样.
这是pythonic的方法。此功能将允许您在所有级别中遍历键值对。它不会将整个内容保存到内存中,而是在您遍历字典时逐步执行
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)
Run Code Online (Sandbox Code Playgroud)
版画
a {1: {1: 2, 3: 4}, 2: {5: 6}}
1 {1: 2, 3: 4}
1 2
3 4
2 {5: 6}
5 6
Run Code Online (Sandbox Code Playgroud)