我们有这样的数据

input = {
    'a': 3,
    'b': {'g': {'l': 12}},
    'c': {
        'q': 3,
        'w': {'v': 3},
        'r': 8,
        'g': 4
    },
    'd': 4
}

事先不知道将有多少个嵌套级别 我们需要获取最终值的完整地址,所有点都用点或另一个特殊字符分隔 就像这样:

a:3
b.g.l: 12
c.q: 3
c.w.v: 3
etc

我试着用递归函数来解决这个问题.

def recursive_parse(data: dict, cache: Optional[list]=None):
    if cache is None:
        cache = []
    for k in data:
        cache.append(k)
        if not isinstance(data[k], dict):
            print(f"{'.'.join(cache) } :{data[k]}")
            cache.clear()
        else:
            recursive_parse(data[k], cache)

但我在"记住"嵌套词典的前一个关键字时遇到了问题.

a :3
b.g.l :12
c.q :3
w.v :3
r :8
g :4
d :4

解决此问题的正确算法是什么?

推荐答案

对于这一点,使用显式堆栈可能比使用Python调用堆栈更好.由于较高的函数调用开销,在Python中递归速度很慢,并且递归限制相当保守.

def dotted(data):
    result = {}
    stack = list(data.items())
    while stack:
        k0, v0 = stack.pop()
        if isinstance(v0, dict):
            for k1, v1 in v0.items():
                item = ".".join([k0, k1]), v1
                stack.append(item)
        else:
            result[k0] = v0
    return result

演示:

>>> data
{'a': 3,
 'b': {'g': {'l': 12}},
 'c': {'q': 3, 'w': {'v': 3}, 'r': 8, 'g': 4},
 'd': 4}
>>> for k, v in reversed(dotted(data).items()):
...     print(k, v)
... 
a 3
b.g.l 12
c.q 3
c.w.v 3
c.r 8
c.g 4
d 4

Python-3.x相关问答推荐

Pyvis和Networkx:如何根据源或目标使 node colored颜色 不同

泛型类型的参数的静态类型

将列表转换为 pandas 数据框,其中列表包含字典

添加任意数量的 pandas 数据框

如何使用Selenium从网站下拉菜单中获取值列表?

基于组/ID从原始数据框中创建两个子数据框

使用正则表达式捕获组解析地址

Python:获取未绑定的类方法

将变量传递给 Google Cloud 函数

TypeError:JSON 对象必须是 str,而不是 'dict'

获取比较多列的最大值并返回特定值

为什么Pandas会在 NaN 上合并?

如何用pymongo连接远程mongodb

如何调试垂死的 Jupyter Python3 内核?

如何将numpy数组图像转换为字节?

用于 unicode 大写单词的 Python 正则表达式

Python3 - 如何从现有抽象类定义抽象子类?

同步调用协程

如何对字典的函数输出列表进行单元测试?

Python:如何在 Windows 资源管理器中打开文件夹(Python 3.6.2、Windows 10)