问题
I'm currently working with a recursive function in Python, and I've run into a wall. As titled, the problem is to return the maximum depth of an arbitrarily nested list.
Here is what I have so far:
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
I feel that the problem is with my recursive calls (this may be obvious). It will indeed return var when the list has reached the end, but when I have a nonempty list, things go awry. Nothing is returned at all.
Am I slicing wrong? Should I be doing something before the slice in the recursive call?
The problem may also be with my base case.
回答1:
If they are just nested lists, e.g., [[[], []], [], [[]]]
, here's a nice solution:
def depthCount(lst):
return 1 + max(map(depthCount, lst), default=0)
Here's a slight variation you could use if you don't use Python 3.4, where the default
argument was introduced:
def depthCount(lst):
return len(lst) and 1 + max(map(depthCount, lst))
They also differ by how they count. The first considers the empty list to be depth 1, the second to be depth 0. The first one is easy to adapt, though, just make the default -1.
If they're not just nested lists, e.g., [[[1], 'a', [-5.5]], [(6,3)], [['hi']]])
, here are adaptions to that:
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))
Make sure you understand how the latter one works. If you don't know it yet, it'll teach you how and
works in Python :-)
Taking the "purely recursive" challenge:
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))
Granted, the extra argument is slightly ugly, but I think it's ok.
回答2:
It will indeed return var when the list has reached the end, but when I have a nonempty list, things go awry. Nothing is returned at all.
That's because you have no return
statement, except in the else
base case for an empty list. And if you fall off the end of the function without hitting a return
, that means the function returns None
.
But you have another problem on top of that. You're starting var = 0
, then possibly doing var += 1
… but you're not passing that down into the recursive calls, or using any result from the recursive calls. So the recursive calls have no useful effect at all.
What you probably meant is something like this:
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
But this still isn't actually right. The depth count of a list is 1 more than the depth count of its deepest element. Just checking its second element won't do you any good; you need to check all of them. So, what you really want is something like this:
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
If you want to replace that iterative for x in lst
with a second layer of recursion, of course you can, but I can't see any good reason to do so; it just makes the code more complicated for no reason. For example:
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
This may still not be right. It definitely does the right thing for, e.g., [1, [2,3], [4, [5]]]
. But what should it do for, say, []
? I can't tell from your question. If it should return 0
or 1
, you'll obviously need to change the if
appropriately. If that's illegal input, then it's already doing the right thing. (And that should also answer the question of what it should do for, e.g., [[[], []], [], [[]]]
, but make sure you think through that case as well.)
回答3:
So, essentially, the data structure that you're referring to is a k-ary tree, also known as n-ary tree, with arbitrary branching. Here's the code for determining the max. depth of a n-ary tree with arbitrary branching.
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
You can see the code in action with different test inputs here.
来源:https://stackoverflow.com/questions/30427268/on-finding-the-maximum-depth-of-an-arbitrarily-nested-list