Loop through categories recursively
<p>I'm building a python function which returns an array to be used in a select dropdown field. I have tried two versions so far. </p>

<p>Both of them work, with the first returning a properly formatted select field. However, the first solution only goes two levels deep. I intend to add more depth to the categories. </p>

<p>My second example is my attempt at doing this recursively to support more levels. It works but I'm wondering how I can optimize it and add dashes similar to the first example.</p>

<pre><code># first example two levels deep, formatted properly with dashes
def build_choice_tree():
    categories = Category.query.get(1).children
    items = [(1, 'None')]
    for root in categories:
        items.append((root.id, root.name))
        if root.children:
            for subcat1 in root.children:
                items.append((subcat1.id, '- ' + subcat1.name))
                if subcat1.children:
                    for subcat2 in subcat1.children:
                        items.append((subcat2.id, '--' + subcat2.name))
    return items

# second example goes multiple levels, needs dashes
def build_choice_tree2():
    categories = Category.query.get(1).children
    items = []

    def loop(categories):
        for category in categories:
            items.append((category.id, category.name))
            if category.children:
                loop(category.children)
        return items
    result = loop(categories)
    return result
</code></pre>

<p>Use a counter to store the number of dashes you want to add and multiply the dashes by that count. Also to make a function truly recursive you need to add the <code>return</code> statement.</p>

<pre><code>def build_choice_tree2():
    categories = Category.query.get(1).children
    items = []
    count = 1

    def loop(categories, count):
        for category in categories:
            items.append((category.id,'-' * count, category.name))
            if category.children:
                count +=1
                return loop(category.children, count)
        return items

    return loop(categories, count)
</code></pre>

<p>Personally i would separate <code>loop</code> into a different method like this and avoid the inner <code>loop</code> method in build_choice_tree2. i'll also make <code>items</code> a default argument. since default arguments (mutable) are evaluated at function definition time, it will never get reset to it's original value of an empty list.</p>

<pre><code>def loop(categories, count=1, items=[]):
    for category in categories:
        items.append((category.id,'-' * count, category.name))
        if category.children:
            count +=1
            return loop(category.children, count)
    return items
</code></pre>

python recursion