【问题标题】: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 表明这是家庭作业,然后适当地提出问题。这个问题既有趣,又展示了迄今为止的尝试。

标签: python list nested levels


【解决方案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
                  

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

                  【讨论】:

                    猜你喜欢
                    • 2013-08-22
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 1970-01-01
                    • 2018-04-14
                    • 2022-10-16
                    相关资源
                    最近更新 更多