我需要在JSON对象中的所有叶子上使用迭代器。所以我写了这个函数
rec = {'a': {'b': [{'c': {'d': [{'e': 'x1','f': 'x2'}],'g': 'x3'}}],'h': 'x4','i': 'x5','j': [{'k': 'x6'}],'l': [{'m': {'n': 'x7'}}]}}
def yield_leaves(rec, lbl = ''):
if isinstance(rec, dict):
for key, value in rec.items():
for to_yield in yield_leaves(value, key):
yield to_yield
if isinstance(rec, list):
for value in rec:
for to_yield in yield_leaves(value, lbl):
yield to_yield
if isinstance(rec, (int, str)):
for entry in rec.split():
yield entry, lbl
print(list(yield_leaves(rec)))
>>> [('x5', 'i'), ('x4', 'h'), ('x1', 'e'), ('x2', 'f'), ('x3', 'g'), ('x6', 'k'), ('x7', 'n')]
但我认为有些代码是多余的。以下一行
for to_yield in yield_leaves(value, key):
yield to_yield
迭代迭代器并将值作为迭代器的一部分返回。
你知道一种更有效的代码编码方法吗?
答案 0 :(得分:1)
尝试使用yield而不是
yeild from yield_leaves(value, key)
P.S。如果您使用的是python> 3.3
答案 1 :(得分:1)
你的上一节
if isinstance(rec, (int, str)):
for entry in rec.split():
yield entry, lbl
有点奇怪。如果rec
是int
,则会崩溃,因为整数不具有.split
方法。并且您的所有字符串都不包含空格,因此在它们上调用.split
将只返回包含单个项目的列表:原始字符串。我猜你的真实数据可能包含你要分割的多字符串,但如果是这样,你真的需要单独处理int
s。
因此,假设您不具有您希望拆分的多字词值,我已经简化了您的代码。如您所见,我只保留了dict
和list
测试,由于数据是从JSON解码的,因此任何其他rec
类型都将是某种标量:{ {1}},int
,str
或bool
,(除非您已创建自定义解码),我们可以完全相同地处理所有这些标量类型。
None
<强>输出强>
rec = {
'a': {
'b': [
{
'c': {
'd': [{'e': 'x1', 'f': 'x2'}],
'g': 'x3'
}
}
],
'h': 'x4',
'i': 'x5',
'j': [{'k': 'x6'}],
'l': [{'m': {'n': 'x7'}}]
}
}
def yield_leaves(rec, lbl=''):
if isinstance(rec, dict):
for key, value in rec.items():
yield from yield_leaves(value, key)
elif isinstance(rec, list):
for value in rec:
yield from yield_leaves(value, lbl)
else:
yield rec, lbl
print(list(yield_leaves(rec)))
此代码使用Python 3功能[('x1', 'e'), ('x2', 'f'), ('x3', 'g'), ('x4', 'h'), ('x5', 'i'), ('x6', 'k'), ('x7', 'n')]
;如果您不使用Python 3,那么您应该这样做。 :)