ok1*_*ump 6 python recursion dictionary global list
我最近不得不用嵌套的字典/列表组合解决实际数据系统中的问题.我在这方面工作了很长一段时间并提出了一个解决方案,但我非常不满意.我不得不求助于使用globals()和命名的临时全局参数.
我不喜欢使用全局变量.这只是要求注射漏洞.我觉得必须有更好的方法来执行这项任务而不诉诸全局变量.
问题数据集:
d = {
"k":1,
"stuff":"s1",
"l":{"m":[
{
"k":2,
"stuff":"s2",
"l":None
},
{
"k":3,
"stuff":"s3",
"l":{"m":[
{
"k":4,
"stuff":"s4",
"l":None
},
{
"k":5,
"stuff":"s5",
"l":{"m":[
{
"k":6,
"stuff":"s6",
"l":None
},
]}
},
]}
},
]}
}
Run Code Online (Sandbox Code Playgroud)
期望的输出:
[{'k': 1, 'stuff': 's1'},
{'k': 2, 'stuff': 's2'},
{'k': 3, 'stuff': 's3'},
{'k': 4, 'stuff': 's4'},
{'k': 5, 'stuff': 's5'},
{'k': 6, 'stuff': 's6'}]
Run Code Online (Sandbox Code Playgroud)
我的解决方案
def _get_recursive_results(d, iter_key, get_keys):
if not 'h' in globals():
global h
h = []
h.append({k:d.get(k) for k in get_keys})
d2 = d.copy()
for k in iter_key:
if not d2:
continue
d2 = d2.get(k)
for td in d2:
d3 = td.copy()
for k in iter_key:
if not d3:
continue
d3 = d3.get(k)
if d3:
return _get_recursive_results(td, iter_key, get_keys)
h.append({k:td.get(k) for k in get_keys})
else:
l = [k for k in h]
del globals()['h']
return l
Run Code Online (Sandbox Code Playgroud)
按如下方式调用我的函数会返回所需的结果:
_get_recursively(d, ['l','m'], ['k','stuff'])
Run Code Online (Sandbox Code Playgroud)
我将如何构建更好的解决方案?
这是一个稍微修改过的版本,没有使用全局变量.设置h到None
默认,并为第一次调用一个新的列表_get_recursive_results().稍后h在递归调用中提供作为参数_get_recursive_results():
def _get_recursive_results(d, iter_key, get_keys, h=None):
if h is None:
h = []
h.append({k:d.get(k) for k in get_keys})
d2 = d.copy()
for k in iter_key:
if not d2:
continue
d2 = d2.get(k)
for td in d2:
d3 = td.copy()
for k in iter_key:
if not d3:
continue
d3 = d3.get(k)
if d3:
return _get_recursive_results(td, iter_key, get_keys, h)
h.append({k:td.get(k) for k in get_keys})
else:
l = [k for k in h]
return l
Run Code Online (Sandbox Code Playgroud)
现在:
>>> _get_recursive_results(d, ['l','m'], ['k','stuff'])
[{'k': 1, 'stuff': 's1'},
{'k': 2, 'stuff': 's2'},
{'k': 3, 'stuff': 's3'},
{'k': 4, 'stuff': 's4'},
{'k': 5, 'stuff': 's5'},
{'k': 6, 'stuff': 's6'}]
Run Code Online (Sandbox Code Playgroud)
不需要复制中间词.这是一个没有复制的进一步修改版本:
def _get_recursive_results(d, iter_key, get_keys, h=None):
if h is None:
h = []
h.append({k: d.get(k) for k in get_keys})
for k in iter_key:
if not d:
continue
d = d.get(k)
for td in d:
d3 = td
for k in iter_key:
if not d3:
continue
d3 = d3.get(k)
if d3:
return _get_recursive_results(td, iter_key, get_keys, h)
h.append({k: td.get(k) for k in get_keys})
else:
return h
Run Code Online (Sandbox Code Playgroud)
这不是通用的,但它完成了工作:
def parse_tree(d, keys):
result = [{key: d[key] for key in keys}]
l = d.get('l', None)
if l is not None:
entries = l.get('m', [])
for entry in entries:
result.extend(parse_tree(entry))
return result
>>> parse_tree(d, ['k', 'stuff'])
[{'k': 1, 'stuff': 's1'},
{'k': 2, 'stuff': 's2'},
{'k': 3, 'stuff': 's3'},
{'k': 4, 'stuff': 's4'},
{'k': 5, 'stuff': 's5'},
{'k': 6, 'stuff': 's6'}]
Run Code Online (Sandbox Code Playgroud)