2016-04-22 127 views
3

我有一个非常简单的组合问题。我有两个数组(a和b)。数组a表示数组b中的三个插槽中的一个可以采用的所有值。数组b中的每个插槽可以具有1到5之间的值。其中的一个例子是[1,4,5]。我想用所有可能的组合生成一个数组(c)。我喜欢扩展更大阵列的基本示例。[Python]:生成和排列所有可能的组合

输入:

a = [1, 2, 3, 4, 5] 
b = [1, 2, 3] 

输出:

c = [[1, 1, 1], [1, 1, 2],[1, 1, 3], [1, 1, 4], [1, 1, 5], 
    [1, 2, 1], [1, 2, 2],[1, 2, 3], [1, 2, 4], [1, 2, 5], 
    [1, 3, 1], [1, 3, 2],[1, 3, 3], [1, 3, 4], [1, 3, 5], 
    [1, 4, 1], [1, 4, 2],[1, 4, 3], [1, 4, 4], [1, 4, 5], 
    [1, 5, 1], [1, 5, 2],[1, 5, 3], [1, 5, 4], [1, 5, 5], 
    [2, 1, 1], [2, 1, 2],[2, 1, 3], [2, 1, 4], [2, 1, 5], 
    [2, 2, 1], [2, 2, 2],[2, 2, 3], [2, 2, 4], [2, 2, 5], 
    [2, 3, 1], [2, 3, 2],[2, 3, 3], [2, 3, 4], [2, 3, 5], 
    [2, 4, 1], [2, 4, 2],[2, 4, 3], [2, 4, 4], [2, 4, 5], 
    [2, 5, 1], [2, 5, 2],[2, 5, 3], [2, 5, 4], [2, 5, 5], 
    [3, 1, 1], [3, 1, 2],[3, 1, 3], [3, 1, 4], [3, 1, 5], 
    [3, 2, 1], [3, 2, 2],[3, 2, 3], [3, 2, 4], [3, 2, 5], 
    [3, 3, 1], [3, 3, 2],[3, 3, 3], [3, 3, 4], [3, 3, 5], 
    [3, 4, 1], [3, 4, 2],[3, 4, 3], [3, 4, 4], [3, 4, 5], 
    [3, 5, 1], [3, 5, 2],[3, 5, 3], [3, 5, 4], [3, 5, 5], 
    [4, 1, 1], [4, 1, 2],[4, 1, 3], [4, 1, 4], [4, 1, 5], 
    [4, 2, 1], [4, 2, 2],[4, 2, 3], [4, 2, 4], [4, 2, 5], 
    [4, 3, 1], [4, 3, 2],[4, 3, 3], [4, 3, 4], [4, 3, 5], 
    [4, 4, 1], [4, 4, 2],[4, 4, 3], [4, 4, 4], [4, 4, 5], 
    [5, 5, 1], [5, 5, 2],[5, 5, 3], [5, 5, 4], [5, 5, 5], 
    [5, 1, 1], [5, 1, 2],[5, 1, 3], [5, 1, 4], [5, 1, 5], 
    [5, 2, 1], [5, 2, 2],[5, 2, 3], [5, 2, 4], [5, 2, 5], 
    [5, 3, 1], [5, 3, 2],[5, 3, 3], [5, 3, 4], [5, 3, 5], 
    [5, 4, 1], [5, 4, 2],[5, 4, 3], [5, 4, 4], [5, 4, 5], 
    [5, 5, 1], [5, 5, 2],[5, 5, 3], [5, 5, 4], [5, 5, 5]] 

解决以上问题:

d = [] 
for i in range(len(a)): 
    for j in range(len(a)): 
     for k in range(len(a)): 
      e = [] 
      e.append(i+1) 
      e.append(j+1) 
      e.append(k+1) 
      d.append(e) 

我正在寻找一种更通用的方法。一个可以容纳更大的数组(见下面)而不需要使用嵌套for循环结构。我搜索了一个可比较的例子,但无法在stackoverflow上找到它。

输入:

a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] 
b = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20] 
+1

看看python [itertools](https://docs.python.org/2/library/itertools.html)。组合方法可以做我认为你正在寻找的东西。 – Jggrnaut

+2

从你的描述来看,我也不认为你需要一个'b'数组,只是一个整数值来指定数组的长度 – wilkesybear

+0

当我对一系列公差变量进行MonteCarlo模拟时,我有类似的问题,但是我发现生成一个所有可能组合的数组是无意义的,当它非常容易时(请参阅您自己的代码)即时生成这些组合。 – roadrunner66

回答

4

您正在寻找itertools.product()

a = [1, 2, 3, 4, 5] 
b = 3 # Actually, you just need the length of the array, values do not matter 

c = itertools.product(a, repeat=b) 

注意它返回一个迭代器,则可能需要将其强制转换使用list()但要注意这可能需要永远和高消耗内存,如果规模增长。

1

在一般情况下,您当然应该使用itertools模块,在此特定情况下itertools.product,如其他答案中所述。

如果你想自己实现这个功能,你可以使用递归使它适用于任何数组大小。此外,您应该使其成为发电机功能(使用yield而不是return),因为结果可能会相当长。你可以尝试这样的:

def combinations(lst, num): 
    if num > 0: 
     for x in lst: 
      for comb in combinations(lst, num - 1): 
       yield [x] + comb 
    else: 
     yield [] 
相关问题