for k, v in d.iteritems():
if type(v) is dict:
for t, c in v.iteritems():
print "{0} : {1}".format(t, c)
I'm trying to loop through a dictionary and print out all key value pairs where the value is not a nested dictionary. If the value is a dictionary I want to go into it and print out its key value pairs...etc. Any help?
我正在尝试遍历字典并打印出值不是嵌套字典的所有键值对。如果值是字典,我想进入它并打印出其键值对...等。有帮助吗?
EDIT
编辑
How about this? It still only prints one thing.
这个怎么样?它仍然只打印一件事。
def printDict(d):
for k, v in d.iteritems():
if type(v) is dict:
printDict(v)
else:
print "{0} : {1}".format(k, v)
Full Test Case
完整测试案例
Dictionary:
字典:
{u'xml': {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'},
u'port': u'11'}}
Result:
结果:
xml : {u'config': {u'portstatus': {u'status': u'good'}, u'target': u'1'}, u'port': u'11'}
11 个解决方案
#1
82
As said by Niklas, you need recursion, i.e. you want to define a function to print your dict, and if the value is a dict, you want to call your print function using this new dict.
正如Niklas所说,你需要递归,即你想要定义一个函数来打印你的dict,如果值是一个dict,你想用这个新的dict来调用你的打印函数。
Something like :
就像是 :
def myprint(d):
for k, v in d.iteritems():
if isinstance(v, dict):
myprint(v)
else:
print "{0} : {1}".format(k, v)
Or for Python 3 onwards :
或者对于Python 3以上版本:
def myprint(d):
for k, v in d.items():
if isinstance(v, dict):
myprint(v)
else:
print("{0} : {1}".format(k, v))
#2
21
Since a dict
is iterable, you can apply the classic nested container iterable formula to this problem with only a couple of minor changes. Here's a Python 2 version (see below for 3):
由于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
Test:
测试:
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)]
In Python 2, It might be possible to create a custom Mapping
that qualifies as a Mapping
but doesn't contain iteritems
, in which case this will fail. The docs don't indicate that iteritems
is required for a Mapping
; on the other hand, the source gives Mapping
types an iteritems
method. So for custom Mappings
, inherit from collections.Mapping
explicitly just in case.
在Python 2中,有可能创建一个自定义映射,该映射可以作为映射但不包含iteritems,在这种情况下,这将失败。文档并未表明映射需要iteritems;另一方面,源为Mapping类型提供了iteritems方法。因此,对于自定义映射,继承自collections.Mapping显式以防万一。
In Python 3, there are a number of improvements to be made. As of Python 3.3, abstract base classes live in collections.abc
. They remain in collections
too for backwards compatibility, but it's nicer having our abstract base classes together in one namespace. So this imports abc
from collections
. Python 3.3 also adds yield from
, which is designed for just these sorts of situations. This is not empty syntactic sugar; it may lead to faster code and more sensible interactions with coroutines.
在Python 3中,有许多改进。从Python 3.3开始,抽象基类存在于collections.abc中。它们仍然保留在集合中以便向后兼容,但是在一个命名空间中将抽象基类放在一起会更好。所以这从集合中导入abc。 Python 3.3还增加了yield,它仅针对这些情况而设计。这不是空的句法糖;它可能会导致更快的代码和与协程的更明智的交互。
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
#3
17
Alternative iterative solution:
替代迭代解决方案:
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))
#4
13
There are potential problems if you write your own recursive implementation or the iterative equivalent with stack. See this example:
如果您编写自己的递归实现或迭代等效的堆栈,则存在潜在的问题。看这个例子:
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
In the normal sense, nested dictionary will be a n-nary tree like data structure. But the definition doesn't exclude the possibility of a cross edge or even a back edge (thus no longer a tree). For instance, here key2.2 holds to the dictionary from key1, key2.3 points to the entire dictionary(back edge/cycle). When there is a back edge(cycle), the stack/recursion will run infinitely.
在通常意义上,嵌套字典将是一个像数据结构一样的n-nary树。但该定义并未排除交叉边缘甚至后边缘(因此不再是树)的可能性。例如,这里key2.2从key1保持字典,key2.3指向整个字典(后边缘/循环)。当存在后沿(循环)时,堆栈/递归将无限运行。
root<-------back edge
/ \ |
_key1 __key2__ |
/ / \ \ |
|->key1.1 key2.1 key2.2 key2.3
| / | |
| value1 value2 |
| |
cross edge----------|
If you print this dictionary with this implementation from Scharron
如果您使用Scharron的此实现打印此字典
def myprint(d):
for k, v in d.iteritems():
if isinstance(v, dict):
myprint(v)
else:
print "{0} : {1}".format(k, v)
You would see this error:
你会看到这个错误:
RuntimeError: maximum recursion depth exceeded while calling a Python object
The same goes with the implementation from senderle.
来自senderle的实现也是如此。
Similarly, you get an infinite loop with this implementation from Fred Foo:
类似地,你从Fred Foo获得这个实现的无限循环:
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))
However, Python actually detects cycles in nested dictionary:
但是,Python实际上会检测嵌套字典中的循环:
print dic
{'key2': {'key2.1': 'value2', 'key2.3': {...},
'key2.2': {'key1.1': 'value1'}}, 'key1': {'key1.1': 'value1'}}
"{...}" is where a cycle is detected.
“{...}”是检测到循环的地方。
As requested by Moondra this is a way to avoid cycles (DFS):
根据Moondra的要求,这是一种避免循环的方法(DFS):
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)
#5
4
Here is pythonic way to do it. This function will allow you to loop through key-value pair in all the levels. It does not save the whole thing to the memory but rather walks through the dict as you loop through it
这是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)
Prints
打印
a {1: {1: 2, 3: 4}, 2: {5: 6}}
1 {1: 2, 3: 4}
1 2
3 4
2 {5: 6}
5 6
#6
4
Slightly different version I wrote that keeps track of the keys along the way to get there
我编写的版本略有不同,可以跟踪到达目的地的密钥
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)))
On your data, it'll print
在您的数据上,它将打印出来
data['xml']['config']['portstatus']['status'] = u'good'
data['xml']['config']['target'] = u'1'
data['xml']['port'] = u'11'
It's also easy to modify it to track the prefix as a tuple of keys rather than a string if you need it that way.
它也很容易修改它来跟踪前缀作为键的元组而不是字符串,如果你需要它那样。
#7
1
Iterative solution as an alternative:
迭代解决方案作为替代方案:
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
#8
1
A alternative solution to work with lists based on Scharron's solution
使用基于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)
#9
1
Here's a modified version of Fred Foo's answer for Python 2. In the original response, only the deepest level of nesting is output. If you output the keys as lists, you can keep the keys for all levels, although to reference them you need to reference a list of lists.
这是Fred Foo对Python 2的回答的修改版本。在原始响应中,只输出最深层次的嵌套。如果将键输出为列表,则可以保留所有级别的键,但要引用它们,您需要引用列表列表。
Here's the function:
这是功能:
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
To reference the keys:
要引用密钥:
for keys, vals in mynested:
print(mynested[keys[0]][keys[1][0]][keys[1][1][0]])
for a three-level dictionary.
对于三级字典。
You need to know the number of levels before to access multiple keys and the number of levels should be constant (it may be possible to add a small bit of script to check the number of nesting levels when iterating through values, but I haven't yet looked at this).
你需要知道访问多个密钥之前的级别数量,级别的数量应该是不变的(在迭代值时可以添加一小部分脚本来检查嵌套级别的数量,但我还没有但看着这个)。
#10
0
I find this approach a bit more flexible, here you just providing generator function that emits key, value pairs and can be easily extended to also iterate over lists.
我发现这种方法更灵活一些,在这里你只需要提供生成键,值对的生成器函数,并且可以很容易地扩展到迭代列表。
def traverse(value, key=None):
if isinstance(value, dict):
for k, v in value.items():
yield from traverse(v, k)
else:
yield key, value
Then you can write your own myprint
function, then would print those key value pairs.
然后你可以编写自己的myprint函数,然后打印这些键值对。
def myprint(d):
for k, v in traverse(d):
print(f"{k} : {v}")
A test:
一个测试:
myprint({
'xml': {
'config': {
'portstatus': {
'status': 'good',
},
'target': '1',
},
'port': '11',
},
})
Output:
输出:
status : good
target : 1
port : 11
I tested this on Python 3.6.
我在Python 3.6上测试了这个。
#11
0
I am using the following code to print all the values of a nested dictionary, taking into account where the value could be a list containing dictionaries. This was useful to me when parsing a JSON file into a dictionary and needing to quickly check whether any of its values are None
.
我使用以下代码打印嵌套字典的所有值,考虑到值可能是包含字典的列表。在将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)
Output:
输出:
10
2017-03-15T14:02:49.301000
bar
some_string
#1
82
As said by Niklas, you need recursion, i.e. you want to define a function to print your dict, and if the value is a dict, you want to call your print function using this new dict.
正如Niklas所说,你需要递归,即你想要定义一个函数来打印你的dict,如果值是一个dict,你想用这个新的dict来调用你的打印函数。
Something like :
就像是 :
def myprint(d):
for k, v in d.iteritems():
if isinstance(v, dict):
myprint(v)
else:
print "{0} : {1}".format(k, v)
Or for Python 3 onwards :
或者对于Python 3以上版本:
def myprint(d):
for k, v in d.items():
if isinstance(v, dict):
myprint(v)
else:
print("{0} : {1}".format(k, v))
#2
21
Since a dict
is iterable, you can apply the classic nested container iterable formula to this problem with only a couple of minor changes. Here's a Python 2 version (see below for 3):
由于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
Test:
测试:
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)]
In Python 2, It might be possible to create a custom Mapping
that qualifies as a Mapping
but doesn't contain iteritems
, in which case this will fail. The docs don't indicate that iteritems
is required for a Mapping
; on the other hand, the source gives Mapping
types an iteritems
method. So for custom Mappings
, inherit from collections.Mapping
explicitly just in case.
在Python 2中,有可能创建一个自定义映射,该映射可以作为映射但不包含iteritems,在这种情况下,这将失败。文档并未表明映射需要iteritems;另一方面,源为Mapping类型提供了iteritems方法。因此,对于自定义映射,继承自collections.Mapping显式以防万一。
In Python 3, there are a number of improvements to be made. As of Python 3.3, abstract base classes live in collections.abc
. They remain in collections
too for backwards compatibility, but it's nicer having our abstract base classes together in one namespace. So this imports abc
from collections
. Python 3.3 also adds yield from
, which is designed for just these sorts of situations. This is not empty syntactic sugar; it may lead to faster code and more sensible interactions with coroutines.
在Python 3中,有许多改进。从Python 3.3开始,抽象基类存在于collections.abc中。它们仍然保留在集合中以便向后兼容,但是在一个命名空间中将抽象基类放在一起会更好。所以这从集合中导入abc。 Python 3.3还增加了yield,它仅针对这些情况而设计。这不是空的句法糖;它可能会导致更快的代码和与协程的更明智的交互。
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
#3
17
Alternative iterative solution:
替代迭代解决方案:
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))
#4
13
There are potential problems if you write your own recursive implementation or the iterative equivalent with stack. See this example:
如果您编写自己的递归实现或迭代等效的堆栈,则存在潜在的问题。看这个例子:
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
In the normal sense, nested dictionary will be a n-nary tree like data structure. But the definition doesn't exclude the possibility of a cross edge or even a back edge (thus no longer a tree). For instance, here key2.2 holds to the dictionary from key1, key2.3 points to the entire dictionary(back edge/cycle). When there is a back edge(cycle), the stack/recursion will run infinitely.
在通常意义上,嵌套字典将是一个像数据结构一样的n-nary树。但该定义并未排除交叉边缘甚至后边缘(因此不再是树)的可能性。例如,这里key2.2从key1保持字典,key2.3指向整个字典(后边缘/循环)。当存在后沿(循环)时,堆栈/递归将无限运行。
root<-------back edge
/ \ |
_key1 __key2__ |
/ / \ \ |
|->key1.1 key2.1 key2.2 key2.3
| / | |
| value1 value2 |
| |
cross edge----------|
If you print this dictionary with this implementation from Scharron
如果您使用Scharron的此实现打印此字典
def myprint(d):
for k, v in d.iteritems():
if isinstance(v, dict):
myprint(v)
else:
print "{0} : {1}".format(k, v)
You would see this error:
你会看到这个错误:
RuntimeError: maximum recursion depth exceeded while calling a Python object
The same goes with the implementation from senderle.
来自senderle的实现也是如此。
Similarly, you get an infinite loop with this implementation from Fred Foo:
类似地,你从Fred Foo获得这个实现的无限循环:
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))
However, Python actually detects cycles in nested dictionary:
但是,Python实际上会检测嵌套字典中的循环:
print dic
{'key2': {'key2.1': 'value2', 'key2.3': {...},
'key2.2': {'key1.1': 'value1'}}, 'key1': {'key1.1': 'value1'}}
"{...}" is where a cycle is detected.
“{...}”是检测到循环的地方。
As requested by Moondra this is a way to avoid cycles (DFS):
根据Moondra的要求,这是一种避免循环的方法(DFS):
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)
#5
4
Here is pythonic way to do it. This function will allow you to loop through key-value pair in all the levels. It does not save the whole thing to the memory but rather walks through the dict as you loop through it
这是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)
Prints
打印
a {1: {1: 2, 3: 4}, 2: {5: 6}}
1 {1: 2, 3: 4}
1 2
3 4
2 {5: 6}
5 6
#6
4
Slightly different version I wrote that keeps track of the keys along the way to get there
我编写的版本略有不同,可以跟踪到达目的地的密钥
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)))
On your data, it'll print
在您的数据上,它将打印出来
data['xml']['config']['portstatus']['status'] = u'good'
data['xml']['config']['target'] = u'1'
data['xml']['port'] = u'11'
It's also easy to modify it to track the prefix as a tuple of keys rather than a string if you need it that way.
它也很容易修改它来跟踪前缀作为键的元组而不是字符串,如果你需要它那样。
#7
1
Iterative solution as an alternative:
迭代解决方案作为替代方案:
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
#8
1
A alternative solution to work with lists based on Scharron's solution
使用基于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)
#9
1
Here's a modified version of Fred Foo's answer for Python 2. In the original response, only the deepest level of nesting is output. If you output the keys as lists, you can keep the keys for all levels, although to reference them you need to reference a list of lists.
这是Fred Foo对Python 2的回答的修改版本。在原始响应中,只输出最深层次的嵌套。如果将键输出为列表,则可以保留所有级别的键,但要引用它们,您需要引用列表列表。
Here's the function:
这是功能:
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
To reference the keys:
要引用密钥:
for keys, vals in mynested:
print(mynested[keys[0]][keys[1][0]][keys[1][1][0]])
for a three-level dictionary.
对于三级字典。
You need to know the number of levels before to access multiple keys and the number of levels should be constant (it may be possible to add a small bit of script to check the number of nesting levels when iterating through values, but I haven't yet looked at this).
你需要知道访问多个密钥之前的级别数量,级别的数量应该是不变的(在迭代值时可以添加一小部分脚本来检查嵌套级别的数量,但我还没有但看着这个)。
#10
0
I find this approach a bit more flexible, here you just providing generator function that emits key, value pairs and can be easily extended to also iterate over lists.
我发现这种方法更灵活一些,在这里你只需要提供生成键,值对的生成器函数,并且可以很容易地扩展到迭代列表。
def traverse(value, key=None):
if isinstance(value, dict):
for k, v in value.items():
yield from traverse(v, k)
else:
yield key, value
Then you can write your own myprint
function, then would print those key value pairs.
然后你可以编写自己的myprint函数,然后打印这些键值对。
def myprint(d):
for k, v in traverse(d):
print(f"{k} : {v}")
A test:
一个测试:
myprint({
'xml': {
'config': {
'portstatus': {
'status': 'good',
},
'target': '1',
},
'port': '11',
},
})
Output:
输出:
status : good
target : 1
port : 11
I tested this on Python 3.6.
我在Python 3.6上测试了这个。
#11
0
I am using the following code to print all the values of a nested dictionary, taking into account where the value could be a list containing dictionaries. This was useful to me when parsing a JSON file into a dictionary and needing to quickly check whether any of its values are None
.
我使用以下代码打印嵌套字典的所有值,考虑到值可能是包含字典的列表。在将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)
Output:
输出:
10
2017-03-15T14:02:49.301000
bar
some_string