计算深度或嵌套列表的最深级别
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。请改用def
:def 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
奖励:此解决方案计算空列表并避免遍历字符串的陷阱(前提是您要计算空列表)。
【讨论】:
以上是关于计算深度或嵌套列表的最深级别的主要内容,如果未能解决你的问题,请参考以下文章