我创建了一个递归函数来迭代JSON数据,它可以由键和值对组成,其中值是列表或字典。在本例中,我希望使用递归函数最终返回不是列表或字典的键和单个值。我试图将当前的每个值存储在collect变量中(这是一个字典),以查看数据通过的位置。但是,我有两个缺少值的问题:
你能找出这些问题的原因吗?如果您能提供以下见解,将不胜感激。你知道吗
以下是重现问题的步骤。你知道吗
数据,可以复制到文本文件并另存为myfile.JSON文件. 你知道吗
{
"output": {
"id": "ABC",
"fee": 155.47,
"details": [
{
"sales": 1000,
"cost": 200.50,
"card": [
{
"a": 0.01,
"up": 100.25555,
"down": 90.25555
},
{
"b": 0.02,
"up": 101.25,
"down": 80.25
}
]
},
{
"sales": 1100,
"cost": 300.75,
"card": [
{
"a": 0.01,
"up": 110.75111,
"down": 80.7111
},
{
"b": 0.02,
"up": 102.25111,
"down": 70.50111
}
]
}
],
"percent": 0.25,
"sales_start": 1000}}
# The following loads the file to a variable
import json
with open ('myfile.json',"r") as f:
data = json.load(f)
# Create the recursion function
collect = {}
def myfunc(x, max_level, level=0, keystr='output'):
global collect
collect = {}
if level <= max_level:
level += 1
if isinstance(x, dict):
for k, v in x.items():
knames = keystr + '-' + k
if isinstance(v, (dict,list)):
myfunc(x[k], max_level, level, knames)
collect.update({'Case1' + '-' + knames + '-lev'+str(level): v})
else:
collect.update({'Case2' + '-' + knames + '-lev'+str(level): v})
elif isinstance(x, list):
for i in range(len(x)):
if isinstance(x[i], (dict, list)):
knames = keystr + '-idx'+str(i)
myfunc(x[i], max_level, level, knames)
collect.update({'Case3' + '-' + knames : x[i]})
else:
collect.update({'Case4' + '-' + knames : x[i]})
else:
for k, v in x.items():
knames = keystr + '-' + k
collect.update({'Case5' + '_' + knames + '-lev'+str(level): v})
return x
创建的函数有一个max\级别,用于控制我希望返回键值对的嵌套深度。 将字符串缝合在一起将有助于确定我们在嵌套中的深度,并创建唯一的键名。你知道吗
# Run the recursion function and output collect
x = data['output']
myfunc(x, 0)
collect
这将输出以下内容:
{'Case1-output-details-lev1': [{'sales': 1000,
'cost': 200.5,
'card': [{'a': 0.01, 'up': 100.25555, 'down': 90.25555},
{'b': 0.02, 'up': 101.25, 'down': 80.25}]},
{'sales': 1100,
'cost': 300.75,
'card': [{'a': 0.01, 'up': 110.75111, 'down': 80.7111},
{'b': 0.02, 'up': 102.25111, 'down': 70.50111}]}],
'Case2-output-percent-lev1': 0.25,
'Case2-output-sales_start-lev1': 1000}
这是问题1,上面的输出丢失: 'id':'ABC', “费用”:155.47
# Re-run function creation portion above to reset collection, then the following
myfunc(x, 1)
collect
max\u级别控制要嵌套到JSON中的距离。以上返回以下内容:
{'Case3-output-details-idx1': {'sales': 1100,
'cost': 300.75,
'card': [{'a': 0.01, 'up': 110.75111, 'down': 80.7111},
{'b': 0.02, 'up': 102.25111, 'down': 70.50111}]},
'Case1-output-details-lev1': [{'sales': 1000,
'cost': 200.5,
'card': [{'a': 0.01, 'up': 100.25555, 'down': 90.25555},
{'b': 0.02, 'up': 101.25, 'down': 80.25}]},
{'sales': 1100,
'cost': 300.75,
'card': [{'a': 0.01, 'up': 110.75111, 'down': 80.7111},
{'b': 0.02, 'up': 102.25111, 'down': 70.50111}]}],
'Case2-output-percent-lev1': 0.25,
'Case2-output-sales_start-lev1': 1000}
这是问题2,上面的输出仅返回“Case3-output-details-idx1”,缺少“Case3-output-details-idx0”。对于任意数量的索引值,只返回最后一个。你知道吗
----------下面的确认,尽管没有递归函数。你知道吗
下面的代码模拟递归并显示正确的输出。我的数据文件要大得多,而且会有多个具有不同字典和列表组合的文件,因此需要使用递归。你知道吗
x = data['output']
max_level = 0
level = 0
collect = {}
keystr = 'output'
if level <= max_level:
level += 1
if isinstance(x, dict):
for k, v in x.items():
knames = keystr + '-' + k
if isinstance(v, (dict,list)):
collect.update({'Case1' + '-' + knames + '-lev'+str(level): v})
else:
collect.update({'Case2' + '-' + knames + '-lev'+str(level): v})
elif isinstance(x, list):
for i in range(len(x)):
if isinstance(x[i], (dict, list)):
knames = keystr + '-idx'+str(i)
collect.update({'Case3' + '-' + knames : x[i]})
else:
collect.update({'Case4' + '-' + knames : x[i]})
else:
for k, v in x.items():
knames = keystr + '-' + k
collect.update({'Case5' + '_' + knames + '-lev'+str(level): v})
collect
输出如下,显示返回的id和费用:
{'Case2-output-id-lev1': 'ABC',
'Case2-output-fee-lev1': 155.47,
'Case1-output-details-lev1': [{'sales': 1000,
'cost': 200.5,
'card': [{'a': 0.01, 'up': 100.25555, 'down': 90.25555},
{'b': 0.02, 'up': 101.25, 'down': 80.25}]},
{'sales': 1100,
'cost': 300.75,
'card': [{'a': 0.01, 'up': 110.75111, 'down': 80.7111},
{'b': 0.02, 'up': 102.25111, 'down': 70.50111}]}],
'Case2-output-percent-lev1': 0.25,
'Case2-output-sales_start-lev1': 1000}
# Trying to simulate looking one level into the nest
x = data['output']['details']
max_level = 1
level = 1
keystr = 'output'
collect = {}
if level <= max_level:
level += 1
if isinstance(x, dict):
for k, v in x.items():
knames = keystr + '-' + k
if isinstance(v, (dict,list)):
collect.update({'Case1' + '-' + knames + '-lev'+str(level): v})
else:
collect.update({'Case2' + '-' + knames + '-lev'+str(level): v})
elif isinstance(x, list):
for i in range(len(x)):
if isinstance(x[i], (dict, list)):
knames = keystr + '-idx'+str(i)
collect.update({'Case3' + '-' + knames : x[i]})
else:
collect.update({'Case4' + '-' + knames : x[i]})
else:
for k, v in x.items():
knames = keystr + '-' + k
collect.update({'Case5' + '_' + knames + '-lev'+str(level): v})
collect
上面的代码用“Case3-output-idx0”和“Case3-output-idx1”输出以下内容
{'Case3-output-idx0': {'sales': 1000,
'cost': 200.5,
'card': [{'a': 0.01, 'up': 100.25555, 'down': 90.25555},
{'b': 0.02, 'up': 101.25, 'down': 80.25}]},
'Case3-output-idx1': {'sales': 1100,
'cost': 300.75,
'card': [{'a': 0.01, 'up': 110.75111, 'down': 80.7111},
{'b': 0.02, 'up': 102.25111, 'down': 70.50111}]}}
非常感谢您的复习。你知道吗
进一步研究这些问题后,myfunc()的递归似乎覆盖了变量collect,即使它被指定为函数中的全局变量:
通过删除此项并在函数外部使用常规全局变量,collect变量能够捕获所有值。下面的代码有助于缩小问题的范围。你知道吗
当myfunc()没有在下面注释掉时,递归似乎覆盖了最初存储在collect中的内容,即id和fee值。你知道吗
为了解决这个问题,可以删除函数中的全局变量。你知道吗
接下来是剩下的代码:
然后,我们可以在JSON中进一步嵌套以下内容,其中返回“Case2-output-details-idx0”和“Case2-output-details-idx1”值的每个索引值,这解决了问题2。现在返回所有值。你知道吗
相关问题 更多 >
编程相关推荐