如何编写大量嵌套'for'循环(递归)

时间:2014-11-02 02:42:27

标签: python loops for-loop

word = "word"

# Splitting word into its characters
newword = []
for char in word:
    newword.append(char)

print newword


#getting all permutations
test= []
for i in newword:
    for j in newword:
        if i != j:
            for k in newword:
                if j != k and i!= k:
                    for l in newword:
                        if i != l and j != l and k != l:
                            test.append(i+j+k+l)

print test 
print type(test)
print len(test)

这4个嵌套循环很适合'word',因为它中只有4个字母。 如果我想要与任何给定单词中的字母一样多的'for'循环,我该怎么做? 有什么好玩的吗?

2 个答案:

答案 0 :(得分:8)

In [10]: import itertools

In [11]: word = "word"

In [12]: test = [''.join(perm) for perm in itertools.permutations(word)]

In [13]: test
Out[13]: 
['word',
 'wodr',
 'wrod',
 'wrdo',
 'wdor',
 'wdro',
 'owrd',
 'owdr',
 'orwd',
 'ordw',
 'odwr',
 'odrw',
 'rwod',
 'rwdo',
 'rowd',
 'rodw',
 'rdwo',
 'rdow',
 'dwor',
 'dwro',
 'dowr',
 'dorw',
 'drwo',
 'drow']

答案 1 :(得分:4)

这是您要解决的一般递归问题。 itertools已经包含了几乎所有可能需要的实现的函数。但是,如果您想要了解某些内容,这是实现目标的一种方式。我将列出一个数字列表。在这种情况下,我会查找排列:

[0,1,2, ... ,N-1]

请注意,一旦获得上述排列,您可以简单地将它们用作置换任何内容的索引。那么这样做的一般方法是什么?

让我们先看一下具体案例的结果。对于说[0,1,2,3]的情况。我们要寻找的结果是列表清单:

[[0, 1, 2, 3], [0, 1, 3, 2], [0, 2, 1, 3], [0, 2, 3, 1], [0, 3, 1, 2],
 [0, 3, 2, 1], [1, 0, 2, 3], [1, 0, 3, 2], [1, 2, 0, 3], [1, 2, 3, 0],
 [1, 3, 0, 2], [1, 3, 2, 0], [2, 0, 1, 3], [2, 0, 3, 1], [2, 1, 0, 3],
 [2, 1, 3, 0], [2, 3, 0, 1], [2, 3, 1, 0], [3, 0, 1, 2], [3, 0, 2, 1],
 [3, 1, 0, 2], [3, 1, 2, 0], [3, 2, 0, 1], [3, 2, 1, 0]]

这个想法是编写一个函数,它接受一个列表列表,递增它。考虑一下简单的函数:

def permNums(inp, N=4):
    newInp = []
    for i in inp:
        for j in range(N):
            if j not in i: newInp.append( i+[j] )
    return newInp

现在使用空列表列表执行此函数...

In [22]: permNums([[]])
Out[22]: [[0], [1], [2], [3]]

使用其输出再次运行时会发生什么?

In [23]: permNums(_)
Out[23]:
[[0, 1],
 [0, 2],
 [0, 3],
 [1, 0],
 [1, 2],
 [1, 3],
 [2, 0],
 [2, 1],
 [2, 3],
 [3, 0],
 [3, 1],
 [3, 2]]

再重复一次?

In [24]: permNums(_)
Out[24]:
[[0, 1, 2],
 [0, 1, 3],
 [0, 2, 1],
 [0, 2, 3],
 [0, 3, 1],
 [0, 3, 2],
 [1, 0, 2],
 [1, 0, 3],
 [1, 2, 0],
 [1, 2, 3],
 [1, 3, 0],
 [1, 3, 2],
 [2, 0, 1],
 [2, 0, 3],
 [2, 1, 0],
 [2, 1, 3],
 [2, 3, 0],
 [2, 3, 1],
 [3, 0, 1],
 [3, 0, 2],
 [3, 1, 0],
 [3, 1, 2],
 [3, 2, 0],
 [3, 2, 1]]

再做一次,你会得到你想要的结果。

现在你可以考虑简单的实现:

result = [[]]
for i in range(N): result = permNums(_)

这个解决你的问题(你只需要将索引映射到你的字符串,然后加入结果)。但是,这不是经典的递归。对于递归,您需要执行两个额外的步骤。

  1. 自行调用该功能
  2. 弄清楚这个呼叫本身的业务何时会停止......
  3. 调用函数本身很简单。只需替换

    return newInp
    

    return permNums(newInp, N)
    

    这一步应该不足为奇,因为这正是您在iPython控制台上手动执行的操作。但是,您需要在某个时候停下来。在这种特定情况下,停止标准应该是简单的。如果其中一个内部列表== N中的元素数量,则停止。

    因此修改后的程序有两个简单的补充:

    def permNums(inp, N=4):
    
        if len(inp[0]) == N: return inp # stopping criterion
    
        newInp = []
        for i in inp:
            for j in range(N):
                if j not in i: newInp.append( i+[j] )
    
        return permNums(newInp, N) # keep calling itself 
    
    print permNums([[]])    
    

    希望这会有所帮助......