【问题标题】:Preserving the current value of a local variable when there is recursion存在递归时保留局部变量的当前值
【发布时间】:2016-06-30 05:46:06
【问题描述】:

我正在编写一个函数来展平嵌套数组 (Python list)。例如将 [1,2,[3]] 变为 [1,2,3],将 [[1,2,[3]],4] 变为 [1,2,3,4] 等。

我有以下几点:

def flatten_array(array):
    flattened_array = []
    for item in array:
        if not isinstance(item, list):
            flattened_array.append(item)
        else:
            flatten_array(item)
    return flattened_array

所以想法是让函数递归,以处理嵌套到未知深度的情况。我的问题是 flattened_array 每次遇到嵌套列表时都会重新初始化(当递归调用 flatten_array 时)。

print flatten_array([1,2,[3]])
[1,2]

当进行递归调用时,如何保持flattened_array 的状态?

【问题讨论】:

    标签: python list recursion multidimensional-array nested


    【解决方案1】:

    换行

    else:
        flatten_array(item)
    

    else:
        flattened_array+=flatten_array(item)
    

    所以完整的功能看起来像

    def flatten_array(array):
        flattened_array = []
        for item in array:
            if not isinstance(item, list):
                flattened_array.append(item)
            else:
                flattened_array+=flatten_array(item)
        return flattened_array
    

    这给了

    flatten_array([1,2,[3]]) # [1,2,3]
    flatten_array([1,2,[3,[4,5]]]) # [1,2,3,4,5]
    flatten_array([1,2,[3,[4,5]],6,7,[8]]) # [1,2,3,4,5,6,7,8]
    

    您的原始代码没有对递归调用做任何事情。您会在列表中取回结果,但只需将其丢弃。我们要做的是将它附加到现有列表的末尾。


    此外,如果您不想继续创建临时数组,我们可以在第一次调用函数时创建一个数组,然后追加到它上面。

    def flatten_array(array,flattened_array=None):
        if flattened_array is None:
            flattened_array = []
        for item in array:
            if not isinstance(item,list):
                flattened_array.append(item)
            else:
                flatten_array(item,flattened_array)
        return flattened_array
    

    这个版本的结果是一样的,也可以用同样的方式,但是在原来的版本中,每次调用函数都会创建一个新的空数组来处理。通常这不是问题,但根据深度或子数组的大小,这可能会在内存中累积。

    此版本将数组扁平化为给定数组。当仅使用输入调用时(如flatten_array([1,2,[3]])),它会创建一个空数组来处理,否则它只会添加到给定数组(因此递归调用只需要给数组添加),就地修改它.

    如果我们愿意,这具有允许您添加到现有数组的优势:

    a = [1,2,3]
    b = [2,3,[4]] # we want to add flatten this to the end of a
    flatten_array(b,a) # we don't bother catching the return result here
    print(a) # [1,2,3,2,3,4]
    


    这里有一个微妙的地方。你可能会问为什么我们没有将函数定义为def flatten_array(array,flattened_array=[]) 并去掉函数内部的测试。尝试并调用该函数几次。发生的情况是在函数定义时创建一次默认值,而不是每次调用函数时。这意味着在适当位置修改的默认数组由每个函数调用共享,从而导致它累积结果。

    这可能不是我们想要的。通过将默认值设置为 None 并每次在函数内部创建一个新的空数组,我们确保对函数的每次调用都有一个唯一的空数组可供使用。

    【讨论】:

    • 谢谢。不知道 + 运算符可用于附加到列表。
    • @Pyderman 这并不完全是附加的。它将两个列表合并在一起。如果要向列表中添加项目,则需要使用 append 方法,但如果您有两个列表并且想要将一个连接到另一个列表的末尾,则可以添加它们。请注意,如果您学过很多代数,这是非交换加法的一个示例。
    • @Matthew 感谢您的额外详细说明和替代解决方案。
    猜你喜欢
    • 1970-01-01
    • 2020-11-28
    • 1970-01-01
    • 2022-11-25
    • 1970-01-01
    • 1970-01-01
    • 2013-07-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多