I have a database that models a foldering relationship to n
levels of nesting. For any given folder, I want to generate a list of all child folders.
Assuming I have a function called getChildFolders()
, what is the most efficient way to call this kind of recursive loop?
The following code works for 4 levels of nesting, but I'd like more flexibility in either specifying the depth of recursion, or in intelligently stopping the loop when there are no more children to follow.
folder_ids = []
folder_ids.append(folder.id)
for entry in child_folders:
folder_ids.append(entry.id)
child_folders_1 = getChildFolders(entry.id)
for entry_1 in child_folders_1:
folder_ids.append(entry_1.id)
child_folders_2 = getChildFolders(entry_1.id)
for entry_2 in child_folders_2:
folder_ids.append(entry_2.id)
child_folders_3 = getChildFolders(entry_2.id)
for entry_3 in child_folders_3:
folder_ids.append(entry_3.id)
Python also accepts function recursion, which means a defined function can call itself. Recursion is a common mathematical and programming concept. It means that a function calls itself. This has the benefit of meaning that you can loop through data to reach a result.
Following is an example of a recursive function to find the factorial of an integer. Factorial of a number is the product of all the integers from 1 to that number. For example, the factorial of 6 (denoted as 6!) is 1*2*3*4*5*6 = 720 .
A recursive loop is a special type of looping construct where a particular entity tries to invoke itself from within its loop code. Thus the entity keeps calling itself until a specific condition or break is specified.
You surely can use loops in a recursive function. What makes a function recursive is only the fact that the function calls itself at some point in its execution path. However you should have some condition to prevent infinite recursion calls from which your function can't return.
A recursive function is a nice way to do this:
def collect_folders(start, depth=-1)
""" negative depths means unlimited recursion """
folder_ids = []
# recursive function that collects all the ids in `acc`
def recurse(current, depth):
folder_ids.append(current.id)
if depth != 0:
for folder in getChildFolders(current.id):
# recursive call for each subfolder
recurse(folder, depth-1)
recurse(start, depth) # starts the recursion
return folder_ids
I generally avoid recursion like the plague in python because it's slow and because of the whole stack overflow error thing.
def collect_folders(start):
stack = [start.id]
folder_ids = []
while stack:
cur_id = stack.pop()
folder_ids.append(cur_id)
stack.extend(folder.id for folder in getChildFolders(cur_id))
return folder_ids
This assumes that getChildFolders
returns an empty list when there are no children. If it does something else, like return a sentinel value or raise an exception, then modifications will have to be made.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With