计算深度或嵌套列表的最深级别

Posted

技术标签:

【中文标题】计算深度或嵌套列表的最深级别【英文标题】:Counting depth or the deepest level a nested list goes to 【发布时间】:2011-08-27 16:50:33 【问题描述】:

A 有一个真正的问题(并且很头疼)的作业......

我正在上一门介绍性编程课程,我必须编写一个函数,给定一个列表,它将返回它所达到的“最大”深度... 例如:[1,2,3] 将返回 1,[1,[2,3]] 将返回 2...

我已经写了这段代码(这是我能得到的最好的T_T)

def flat(l):
    count=0
    for item in l:
        if isinstance(item,list):
            count+= flat(item)
    return count+1

但是,它显然不能正常工作,因为如果有列表不计入最大深度,它仍然会提高计数器...

例如:当我使用带有 [1,2,[3,4],5,[6],7] 的函数时,它应该返回 2,但它返回 3...

任何想法或帮助将不胜感激^^非常感谢!我已经为此苦苦挣扎了好几个星期了...

【问题讨论】:

我认为你想要的词是“深度”,而不是“深度”。 附带说明:查看 PEP-8。立即形成风格习惯会很好。对于初学者,请使用L 作为列表,而不是l(看起来像1)。 @duffymo 谢谢 ^^ 我的错,我想很明显英语不是我的第一语言 :-) @orokusaki 这真的很有趣^^谢谢!我什至不知道它存在...... +1 表明这是家庭作业,然后适当地提出问题。这个问题既有趣,又展示了迄今为止的尝试。 【参考方案1】:

这是编写函数的一种方式

depth = lambda L: isinstance(L, list) and max(map(depth, L))+1

我认为您缺少的想法是使用max()

【讨论】:

谢谢 ^^ 我喜欢你们能够使用 lambda 简化每个函数的方式 ^^ 我希望有一天能够做到这一点。 这会在空列表上中断,仅供参考 Named lambdas are bad practice。请改用defdef depth(L): return isinstance(L, list) and max(map(depth, L))+1【参考方案2】:

让我们先稍微改一下你的要求。

列表的深度比其子列表的最大深度大一。

现在,这可以直接翻译成代码:

def depth(l):
    if isinstance(l, list):
        return 1 + max(depth(item) for item in l)
    else:
        return 0

【讨论】:

代码需要更正空列表元素,这会导致生成器为max arg 创建一个空序列,从而导致错误。 @Basel 看起来一个最小的修复是在max() 调用之后添加if l else 1【参考方案3】:

递归很简单

def flat(l):
    depths = []
    for item in l:
        if isinstance(item, list):
            depths.append(flat(item))
    if len(depths) > 0:
        return 1 + max(depths)
    return 1

【讨论】:

【参考方案4】:

广度优先,无递归,也适用于其他序列类型:

from collections import Sequence
from itertools import chain, count

def depth(seq):
    for level in count():
        if not seq:
            return level
        seq = list(chain.from_iterable(s for s in seq if isinstance(s, Sequence)))

同样的想法,但内存消耗更少:

from collections import Sequence
from itertools import chain, count

def depth(seq):
    seq = iter(seq)
    try:
        for level in count():
            seq = chain([next(seq)], seq)
            seq = chain.from_iterable(s for s in seq if isinstance(s, Sequence))
    except StopIteration:
        return level

【讨论】:

这将在带有字符串的序列上中断。例如,depth(["a"]) 将中断 只需像seq = chain.from_iterable(s for s in seq if isinstance(s, Sequence) and not isinstance(s, str)) 那样扩展倒数第三行,它也适用于字符串元素【参考方案5】:

在一行python中做到了:)

享受

def f(g,count=0): return count if not isinstance(g,list) else max([f(x,count+1) for x in g])

【讨论】:

【参考方案6】:

一种不需要任何额外模块且速度相同的方式,无论深度如何:

def depth(nested):
    instring = False
    count = 0
    depthlist = []
    for char in repr(nested):
        if char == '"' or char == "'":
            instring = not instring
        elif not instring and ( char == "[" or char == ")" ):
            count += 1
        elif not instring and ( char == "]" or char == ")" ):
            count -= 1
        depthlist.append(count)
    return(max(depthlist))

基本上,它的作用是使用repr() 将列表转换为字符串。然后对于该字符串中等于“(”或“[”的每个字符,它会增加变量count。对于右括号,它减少了count。然后它返回count 达到的最大值。

【讨论】:

【参考方案7】:

辱骂方式: 假设您的列表名为mylist

mybrackets = map(lambda x: 1 if x=='[' else -1, [x for x in str(mylist) if x=='[' or x==']'])  
maxdepth = max([sum(mybrackets[:i+1]) for i in range(len(mybrackets))])

这会将您的列表转换为左括号和右括号的列表,然后找到在相应右括号出现之前出现的最大数量的左括号。

【讨论】:

【参考方案8】:

我为每个可迭代对象扩展了hammar's answer(默认禁用字符串):

def depth(arg, exclude=None):
    if exclude is None:
        exclude = (str, )

    if isinstance(arg, tuple(exclude)):
        return 0

    try:
        if next(iter(arg)) is arg:  # avoid infinite loops
            return 1
    except TypeError:
        return 0

    try:
        depths_in = map(lambda x: depth(x, exclude), arg.values())
    except AttributeError:
        try:
            depths_in = map(lambda x: depth(x, exclude), arg)
        except TypeError:
            return 0

    try:
        depth_in = max(depths_in)
    except ValueError:
        depth_in = 0

    return 1 + depth_in

【讨论】:

【参考方案9】:

Numpy 中,您可以将数据结构转换为 numpy array 并使用其库函数。 arr.shape 给出了每层的长度,所以我们可以len() 得到形状并得到结构的深度:

import numpy as np

def f( lists )
  arr = np.array( lists )
  return len(arr.shape)

f( [[[1,2],[3,4]],[[3,4],[5,6]]] ) # results in 3
f( [[1,2],[3,4]] ) # results in 2
f( [1,2] )  # results in 1
f( [] )  # results in 1

形状的 Numpy 文档:https://docs.scipy.org/doc/numpy/reference/generated/numpy.ndarray.shape.html

【讨论】:

【参考方案10】:

如果您正在寻找快速解决方案

def getDepth(matrix):
    try:
        len(matrix)
        return getDepth(matrix[0]) + 1
    except:
        return 0

【讨论】:

尝试将getDepth(["222"]) 放入您的解释器,然后....【参考方案11】:

对上述内容的简短补充,以便它也可以处理空列表:

def list_depth(list_of_lists):
    if isinstance(list_of_lists, list):
        if(len(list_of_lists) == 0):
            depth = 1
        else:
            depth = 1 + max([list_depth(l) for l in list_of_lists])
    else:
        depth = 0
    return depth

【讨论】:

【参考方案12】:

您也可以仅使用 python 递归地执行此操作:

def depth(L,d):
    max = d
    for i in range(len(L)):
        if type(L[i])==list :
            a = depth(L[i],d+1)
            if a>max :
                 max = a
    return(max)

这个函数是递归的,它的作用是它只会到达列表的最大深度,计算列表的深度,当它向上爬时,它只保留所有嵌套列表中注册的最大深度。

【讨论】:

两个化简:先用函数max,去掉变量a和max;其次,使用foreach循环: def depth(L, d): for itm in L: if type(itm) == list: d = max(depth(itm, d + 1), d) return d【参考方案13】:

@John 的解决方案非常棒,但要解决空列表的情况,例如 [][[]] 或其他嵌套列表,您可能需要执行类似的操作

depth = lambda L: isinstance(L, list) and (max(map(depth, L)) + 1) if str(L) else 1

【讨论】:

【参考方案14】:

让我们坚持原来的、相当优雅的解决方案,并使用max 让它工作。许多其他解决方案使用 lambda 表达式或需要外部库。这个使用“纯”python 并保持简单。

def depth(lst):
    d = 0
    for item in lst:
        if isinstance(item, list):
            d = max(depth(item), d)
    return d + 1

奖励:此解决方案计算空列表并避免遍历字符串的陷阱(前提是您要计算空列表)。

【讨论】:

以上是关于计算深度或嵌套列表的最深级别的主要内容,如果未能解决你的问题,请参考以下文章

计算数据框中特定列(SUM、AVG、STDEV)的所有嵌套级别聚合

Ember 计算属性在绑定到深度嵌套的属性时不会触发

提取嵌套字典和列表中的叶值集,不包括无

PHP如何在递归函数中计算嵌套调用的级别?

1614. 括号的最大嵌套深度

在 NSDictionary 中达到最深的儿童级别