Nested for loops to recursive function in Python
<p>I have three lists, each one with several possible values. </p>

<pre><code>probs = ([0.1,0.1,0.2], \
         [0.7,0.9], \
         [0.5,0.4,0.1])
</code></pre>

<p>I want to test all possible combinations of choosing one element from each list. So, 3*2*3=18 possible combinations in this example. In the end, I want to choose the most favourable combinations according to some criteria. This is:</p>

<pre><code>[&lt;index in row 0&gt; , &lt;index in row 1&gt; , &lt;index in row 2&gt; , &lt;criteria value&gt;]
</code></pre>

<p>I can accomplish my task by using three nested for loops (which I did). However, in the real application of this code, I will have a variable number of lists. Because of that, it seems the solution would be using a recursive function with a for loop inside it (which I did as well). The code:</p>

<pre><code># three rows. Test all combinations of one element from each row
# This is [value form row0, value from row1, value from row2]
# So: 3*2*3 = 18 possible combinations
probs = ([0.1,0.1,0.2], \
         [0.7,0.9], \
         [0.5,0.4,0.1])

meu = [] # The list that will store the best combinations in the recursion


#######################################################

def main():

    choice = [] #the list that will store the best comb in the nested for

# accomplish by nested for loops

    for n0 in range(len(probs[0])):
        for n1 in range(len(probs[1])):
            for n2 in range(len(probs[2])):

                w = probs[0][n0] * probs[1][n1] * probs[2][n2]
                cmb = [n0,n1,n2,w]
                if len(choice) == 0:
                    choice.append(cmb)
                elif len(choice) &lt; 5:
                    for i in range(len(choice)+1):
                        if i == len(choice):
                            choice.append(cmb)
                            break
                        if w &lt; choice[i][3]:
                            choice.insert(i,cmb)
                            break
                else:
                    for i in range(len(choice)):
                        if w &lt; choice[i][3]:
                            choice.insert(i,cmb)
                            del choice[-1]
                            break            


# using recursive function
    combinations(0,[])


    #both results
    print('By loops:')
    print(choice)
    print('By recursion:')
    print(meu)



#######################################################


def combinations(step,cmb):

    # Why does 'meu' needs to be global

    if step &lt; len(probs):
        for i in range(len(probs[step])):
            cmb = cmb[0:step] # I guess this is the same problem I dont understand recursion
                                # But, unlike 'meu', here I could use this workaround
            cmb.append(i)
            combinations(step+1,cmb)


    else:
            w = 1
            for n in range(len(cmb)):
                w *= probs[n][cmb[n]]
            cmb.append(w)

            if len(meu) == 0:
                meu.append(cmb)
            elif len(meu) &lt; 5:
                for i in range(len(meu)+1):
                    if i == len(meu):
                        meu.append(cmb)
                        break
                    if w &lt; meu[i][-1]:
                        meu.insert(i,cmb)
                        break
            else:
                for i in range(len(meu)):
                    if w &lt; meu[i][-1]:
                        meu.insert(i,cmb)
                        del meu[-1]
                        break

            return


######################################################

main()
</code></pre>

<p>It outputs, as I wanted:</p>

<pre><code>By loops:
[[0, 0, 2, 0.006999999999999999], [1, 0, 2, 0.006999999999999999], [0, 1, 2, 0.009000000000000001], [1, 1, 2, 0.009000000000000001], [2, 0, 2, 0.013999999999999999]]
By recursion:
[[0, 0, 2, 0.006999999999999999], [1, 0, 2, 0.006999999999999999], [0, 1, 2, 0.009000000000000001], [1, 1, 2, 0.009000000000000001], [2, 0, 2, 0.013999999999999999]]
</code></pre>

<p>Initially, I wanted to use the 'meu' list as internal of the function, because, I thought, it would be better to avoid global variables (perhaps not... I'm a newbie). The problem was I could not come up with a code that would pass both 'meu' and 'cmb' between depths to give the same effect of the nested loops.</p>

<p>How could I implement a recursive function with internal 'meu' instead of being a global list? What am I missing from recursion concept? Thanks.</p>

<p>++++++++++++++++++++++++++++++++++</p>

<p>Example of a failed function:</p>

<pre><code>def combinations(choice,step,cmb):

    if step &lt; len(probs):
        for i in range(len(probs[step])):
            cmb = cmb[0:step] #workaroud for cmb
            cmb.append(i)
            choice = combinations(choice,step+1,cmb)

    else:
            w = 1
            for n in range(len(cmb)):
                w *= probs[n][cmb[n]]
            cmb.append(w)

            if len(choice) == 0:
                choice.append(cmb)
            elif len(choice) &lt; 5:
                for i in range(len(choice)+1):
                    if i == len(choice):
                        choice.append(cmb)
                        break
                    if w &lt; choice[i][-1]:
                        choice.insert(i,cmb)
                        break
            else:
                for i in range(len(choice)):
                    if w &lt; choice[i][-1]:
                        choice.insert(i,cmb)
                        del choice[-1]
                        break

            return choice
</code></pre>

<p>Called by:</p>

<pre><code>choice = combinations([],0,[])
</code></pre>