Python循序渐进搜索嵌套的键 [英] Python Recursive Search of Dict with Nested Keys

查看:97
本文介绍了Python循序渐进搜索嵌套的键的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近不得不用一个嵌套的dict / list组合来解决真实数据系统中的一个问题。我已经做了很长一段时间,并提出了一个解决方案,但我非常不满意。我不得不诉诸于使用 globals()和一个命名的临时全局参数。



我不喜欢使用全局变量。这只是要求注入漏洞。我觉得必须有一个更好的方式来执行这个任务而不诉诸全局变量。



问题数据集:

  d = {
k:1,
stuff:s1,
l:{m b $ b {
k:2,
stuff:s2,
l:无
},
{
k:3,
stuff:s3,
l:{m:[
{
k:4,
stuff:s4,
l:无
},
{
k:5,
stuff:s5 ,
l:{m:[
{
k:6,
stuff:s6,
l无
},
]}
},
]}
},
]}
}

所需输出:

  [{'k':1,'stuff':'s1'},
{'k':2,'stuff':'s2'},
{'k':3,'stuff':'s3'},
{'k':4,'stuff':'s4'},
{'k'东西':'s5'},
{'k':6,'stuff':'s6'}]

我的解决方案:

  def _get_recursive_results(d,iter_key,get_keys):
如果没有全局变量()中的'h':
全局h
h = []
h.append({k:d.get(k)for get inkey)}

d2 = d.copy()
在iter_key中的k:
如果不是d2:
继续
d2 = d2.get(k)

for d2中的td:
d3 = td.copy()
在iter_key中的k:
如果不是d3:
continue
d3 = d3.get(k )

如果d3:
返回_get_recursive_results(td,iter_key,get_ke ys)
h.append({k:td.get(k)for get inkey)}
else:
l = [k for h in h]
del globals( )['h']
return l

如下所示调用我的函数返回所需的结果:

  _get_recursively(d,['l','m'],['k','stuff'])

如何构建更好的解决方案?

解决方案

这是一个略微修改的版本,而不使用全局变量。将 h 设置为
作为默认值,并为第一次调用创建一个新列表 _get_recursive_results()。稍后在 _get_recursive_results()的递归调用中提供 h 作为参数:

  def _get_recursive_results(d,iter_key,get_keys,h = None):
如果h为None:
h = []
h .append({k:d.get(k)for get inKeys})
d2 = d.copy()
在iter_key中的k:
如果不是d2:
继续
d2 = d2.get(k)
在d2中的td:
d3 = td.copy()
在iter_key中的k:
如果不是d3:
继续
d3 = d3.get(k)
如果d3:
返回_get_recursive_results(td,iter_key,get_keys,h)
h.append({k: td.get(k)for k in get_keys})
else:
l = [k for h in h]
return l

现在:

 >>> _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'}]

不需要复制中间命令。这是一个进一步的修改版本,不复制:

  def _get_recursive_results(d,iter_key,get_keys,h = None):
如果h是None,则
h = []
h.append({k:d.get(k)for get inkey)}
在iter_key中的k:
if不是d:
继续
d = d.get(k)
在d中的td:
d3 = td
在iter_key中的k:
如果不是d3:
continue
d3 = d3.get(k)
如果d3:
返回_get_recursive_results(td,iter_key,get_keys,h)
h.append({ k:get_keys中的k的td.get(k)}
else:
return h


I recently had to solve a problem in a real data system with a nested dict/list combination. I worked on this for quite a while and came up with a solution, but I am very unsatisfied. I had to resort to using globals() and a named temporary global parameter.

I do not like to use globals. That's just asking for an injection vulnerability. I feel that there must be a better way to perform this task without resorting to globals.

Problem Dataset:

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
                        },
                    ]}
                },
            ]}
        },
    ]}
}

Desired Output:

[{'k': 1, 'stuff': 's1'},
 {'k': 2, 'stuff': 's2'},
 {'k': 3, 'stuff': 's3'},
 {'k': 4, 'stuff': 's4'},
 {'k': 5, 'stuff': 's5'},
 {'k': 6, 'stuff': 's6'}]

My Solution:

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

Calling my function as follows returns the desired result:

_get_recursively(d, ['l','m'], ['k','stuff'])

How would I build a better solution?

解决方案

This is a slightly modified version without using globals. Set h to None as default and create a new list for the first call to _get_recursive_results(). Later provide h as an argument in the recursive calls to _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

Now:

>>> _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'}]

There is no need for the copying of intermediate dicts. This is a further modified version without copying:

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

这篇关于Python循序渐进搜索嵌套的键的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆