首页 > 解决方案 > 如何检测递归函数的最后一次调用?

问题描述

我有一个复杂的字典列表,如下所示:

data = [
  {
    "l_1_k": 1,
    "l_1_ch": [
      {
        "l_2_k": 2,
        "l_2_ch": [...more levels]
      },
      {
        "l_2_k": 3,
        "l_2_ch": [...more levels]
      }
    ]
  },
  ...more items
]

我正在尝试将此结构展平为这样的行列表:

list = [
  { "l_1_k": 1, "l_2_k": 2, ... },
  { "l_1_k": 1, "l_2_k": 3, ... },
]

我需要这个列表来构建熊猫数据框。

所以,我正在为每个嵌套级别进行递归,并且在最后一层我试图追加到行列表。

def build_dict(d, row_dict, rows):
    # d is the data dictionary at each nesting level
    # row_dict is the final row dictionary
    # rows is the final list of rows
    for key, value in d.items():
        if not isinstance(value, list):
            row_dict[key] = value
        else:
            for child in value:
                build_dict(child, row_dict, rows)
    rows.append(row_dict) # <- How to detect the last recursion and call the append

我这样调用这个函数:

rows = []
for row in data:
    build_dict(d=row, row_dict={}, rows=rows)

我的问题是如果我不知道有多少嵌套级别,如何检测这个递归函数的最后一次调用。使用当前代码,该行在每个嵌套级别都重复。

或者,是否有更好的方法来获得最终结果?

标签: pythonrecursion

解决方案


在查找了一些想法后,我想到的解决方案是:

  1. 声明以下函数,取自此处
def find_depth(d):
    if isinstance(d, dict):
        return 1 + (max(map(find_depth, d.values())) if d else 0)
    return 0
  1. 在您的函数中,每次深入时递增,如下所示:
def build_dict(d, row_dict, rows, depth=0):
    # depth = 1 for the beginning
    for key, value in d.items():
        if not isinstance(value, list):
            row_dict[key] = value
        else:
            for child in value:
                build_dict(child, row_dict, rows, depth + 1)
  1. 最后,测试你是否达到了最大深度,如果是这样,你可以在函数的末尾附加它。您将需要添加一个额外的变量,您将调用它:
def build_dict(d, row_dict, rows, max_depth, depth=0):
    # depth = 1 for the beginning
    for key, value in d.items():
        if not isinstance(value, list):
            row_dict[key] = value
        else:
            for child in value:
                build_dict(child, row_dict, rows,max_depth, depth + 1)
    if depth == max_depth:
        rows.append(row_dict)
  1. 调用函数为:
    build_dict(d=row, row_dict={}, rows=rows, max_depth=find_depth(data))

请记住,因为我没有可以使用的数据集,可能存在一两个语法错误,但方法应该没问题。


推荐阅读