Python 关于求任意嵌套列表的最大深度

Python 关于求任意嵌套列表的最大深度,python,recursion,Python,Recursion,我目前正在使用Python中的递归函数,我遇到了麻烦。如标题所示,问题是返回任意嵌套列表的最大深度 以下是我到目前为止的情况: def depthCount(lst): 'takes an arbitrarily nested list as a parameter and returns the maximum depth to which the list has nested sub-lists.' var = 0 if len(lst) > 0:

我目前正在使用Python中的递归函数,我遇到了麻烦。如标题所示,问题是返回任意嵌套列表的最大深度

以下是我到目前为止的情况:

def depthCount(lst):
    'takes an arbitrarily nested list as a parameter and returns the maximum depth to which the list has nested sub-lists.'

    var = 0

    if len(lst) > 0:

        if type(lst[0]) == list:
            var += 1
            depthCount(lst[1:])

        else:
            depthCount(lst[1:])

    else:
        return var
我觉得问题在于我的递归调用(这可能是显而易见的)。当列表到达末尾时,它确实会返回var,但是当我有一个非空列表时,事情就会出错。什么也不归还

我切错了吗?我应该在递归调用中的切片之前做些什么吗


这个问题也可能与我的基本情况有关。

因此,本质上,您所指的数据结构是一棵树,也称为n元树,具有任意分支。以下是用于确定具有任意分支的n元树的最大深度的代码

def maxdepth(tree):
    if isleaf(tree):
        return 1
    maximum = 0
    for child in children(tree):
        depth = maxdepth(child)
        if depth > maximum:
            maximum = depth
    return maximum + 1
您可以通过不同的测试输入看到正在运行的代码

当列表到达末尾时,它确实会返回var,但是当我有一个非空列表时,事情就会出错。什么也不归还

这是因为除了空列表的
else
基本情况外,没有
return
语句。如果您从函数的末尾掉下来而没有点击
返回
,则表示函数返回

但除此之外,你还有另一个问题。您开始执行
var=0
,然后可能执行
var+=1
…但您没有将其传递到递归调用中,也没有使用递归调用的任何结果。因此,递归调用根本没有任何有用的效果

你的意思可能是这样的:

def depthCount(lst):
    'takes an arbitrarily nested list as a parameter and returns the maximum depth to which the list has nested sub-lists.'

    if len(lst) > 0:

        if type(lst[0]) == list:
            return 1 + depthCount(lst[1:])
        else:
            return depthCount(lst[1:])

    else:
        return 0
def depthCount(lst):
    'takes an arbitrarily nested list as a parameter and returns the maximum depth to which the list has nested sub-lists.'
    if isinstance(lst, list):
        return 1 + max(depthCount(x) for x in lst)
    else:
        return 0
但事实上这还是不对的。列表的深度计数比其最深元素的深度计数多1。仅仅检查它的第二个元素对你没有任何好处;你需要检查所有这些。所以,你真正想要的是这样的:

def depthCount(lst):
    'takes an arbitrarily nested list as a parameter and returns the maximum depth to which the list has nested sub-lists.'

    if len(lst) > 0:

        if type(lst[0]) == list:
            return 1 + depthCount(lst[1:])
        else:
            return depthCount(lst[1:])

    else:
        return 0
def depthCount(lst):
    'takes an arbitrarily nested list as a parameter and returns the maximum depth to which the list has nested sub-lists.'
    if isinstance(lst, list):
        return 1 + max(depthCount(x) for x in lst)
    else:
        return 0

如果您想用第二层递归替换lst中x的迭代
,当然可以,但我看不出有什么好的理由这样做;它只是无缘无故地使代码更加复杂。例如:

def max_child_count(lst):
    if lst:
        return max(depth_count(lst[0]), max_child_count(lst[1:]))
    else:
        return 0

def depth_count(lst):
    if isinstance(lst, list):
        return 1 + max_child_count(lst)
    else:
        return 0


这可能仍然不对。它确实为您做了正确的事情,例如,
[1、[2,3]、[4、[5]]]
。但是它应该做什么,比如说,
[]
?从你的问题我看不出来。如果它应该返回
0
1
,则显然需要适当地更改
If
。如果这是非法输入,那么它已经做了正确的事情。(这也应该回答它应该做什么的问题,例如,
[[[],[],[],[],[[]]]]
,但请确保您也仔细考虑过这个情况。)

如果它们只是嵌套列表,例如,
[[[],[],[],[[]]]
,这里有一个很好的解决方案:

def depthCount(lst):
    return 1 + max(map(depthCount, lst), default=0)
如果不使用Python 3.4,这里有一个小小的变化,其中引入了
default
参数:

def depthCount(lst):
    return len(lst) and 1 + max(map(depthCount, lst))
它们的计算方式也有所不同。第一个将空列表视为深度1,第二个视为深度0。第一个很容易适应,不过,只需将默认值设为-1


如果它们不仅仅是嵌套列表,例如,
[[1]、'a'、[-5.5]、[(6,3)]、[[[hi']]])
,下面是对它们的一些修改:

def depthCount(x):
    return 1 + max(map(depthCount, x)) if x and isinstance(x, list) else 0

def depthCount(x):
    return int(isinstance(x, list)) and len(x) and 1 + max(map(depthCount, x))
确保您了解后一种方法的工作原理。如果您还不知道,它将教您如何在Python中使用
:-)


接受“纯递归”挑战:

def depthCount(x, depth=0):
    if not x or not isinstance(x, list):
        return depth
    return max(depthCount(x[0], depth+1),
               depthCount(x[1:], depth))

当然,额外的参数有点难看,但我认为这没关系。

如果len(lst)>0:
块中没有
return var
的话,为什么要返回一些东西呢?即使你想键入switch on
list
这样你就不会递归到字符串、元组、dict等中。,您真的想防止递归到
列表的子类中吗?如果没有,请使用isinstance(lst[0],list)
。您能否更具体地描述一下“嵌套列表”的外观?它们是否包含除列表以外的任何内容,或者只是像
[[[]、[[]、[]、[]、[[]]、[[[]]]、[[[]]
这样的内容?谢谢Siddharth,如果您必须在不使用循环的情况下解决此问题,请使用纯递归。。。让我想想。@Typhon:要使它纯粹是递归的,你必须用递归替换这两个循环。最具可读性的方法是使用两个相互递归的函数,如我的答案末尾所示。但你可能不想这么做,我必须同意@abarnert的说法。如果您想纯粹递归地执行此操作,则必须进行相互递归。:)@SiddharthShukla:好吧,你可以用一个函数,通过使用一个标志来有效地编码一个2状态机……但我认为这会使它的可读性降低,而不是提高。你的第一个
depthCount()
[]
上失败<代码>值错误:max()arg是一个空序列
。这是一个bug还是一个特性?@sobolevn:我不确定;你得问问写作业的人。如果它是一个bug,当然很容易修复。如果正确答案应该是
0
,只要将条件更改为
,如果是instance(lst,list)和lst:
。如果它应该是不同的,你会想要一个不同的改变是的,那也行。基本上,不是传递一个标志,而是将它改为push-down而不是push-up递归,并将push-down深度合并到标志中。这是个好主意;我通常不会想到下推,除非我正在尝试编写尾部递归代码(这显然不是),但没有理由不在这里这样做。