如何从所有排列中生成所有可能的组合?

Posted

技术标签:

【中文标题】如何从所有排列中生成所有可能的组合?【英文标题】:How to generate all possible combinations from all permutations? 【发布时间】:2016-03-11 20:02:33 【问题描述】:

我有一个 Python 中 K 元素的所有排列的列表,如下所示:

import itertools
perms = list(itertools.permutations(range(K), K))

我想为这些排列perms 的所有可能组合生成一个矩阵(或列表)M。该矩阵(或列表)的每个元素的大小为N。我该怎么做?

例如,对于K=2,我会得到perms=[(0, 1), (1, 0)]。对于N=3,我想要:

M = [ [(0, 1), (0, 1), (0, 1)],
      [(0, 1), (0, 1), (1, 0)],
      [(0, 1), (1, 0), (0, 1)],
      [(0, 1), (1, 0), (1, 0)],
      [(1, 0), (0, 1), (0, 1)],
      [(1, 0), (0, 1), (1, 0)],
      [(1, 0), (1, 0), (0, 1)],
      [(1, 0), (1, 0), (1, 0)] ]

M 是一个包含8 列表的列表。每个列表的大小为N=3,并包含来自perms 的元素。

对于N=2,我想拥有:

M = [ [(0, 1), (0, 1)],
      [(0, 1), (1, 0)],
      [(1, 0), (0, 1)],
      [(1, 0), (1, 0)] ]

对于N=1,我想拥有:

M = [ [(0, 1), (1, 0)] ] = perms

我不知道我是否正确地表述了我的问题(我认为它可以比这更清楚地重新表述)。

【问题讨论】:

为什么不[(1,0), (1,0), (0,1)]?当您指定N 时,当K 小于N 时,您如何决定如何填充列表? 那是我犯的错误。我将不得不接受一个答案并重新提出我认为的问题。 更新您的问题。 【参考方案1】:

您可以从itertools 使用product

from itertools import permutations, product

perms = permutations(range(2))
cartesian_tuples = product(perms, repeat=3)

# (((0, 1), (0, 1), (0, 1)),
#  ((0, 1), (0, 1), (1, 0)),
#  ((0, 1), (1, 0), (0, 1)),
#  ((0, 1), (1, 0), (1, 0)),
#  ((1, 0), (0, 1), (0, 1)),
#  ((1, 0), (0, 1), (1, 0)),
#  ((1, 0), (1, 0), (0, 1)),
#  ((1, 0), (1, 0), (1, 0)))

如果您需要对任何内容进行多次迭代,您可以手动将各个部分转换为列表。当前的结构由生成器组成,这些生成器将在一次迭代后耗尽,不能再次使用。如果你想要嵌套列表:

cartesian_tuples = map(list, list(product(perms, repeat=3)))

# [[(0, 1), (0, 1), (0, 1)],
#  [(0, 1), (0, 1), (1, 0)],
#  [(0, 1), (1, 0), (0, 1)],
#  [(0, 1), (1, 0), (1, 0)],
#  [(1, 0), (0, 1), (0, 1)],
#  [(1, 0), (0, 1), (1, 0)],
#  [(1, 0), (1, 0), (0, 1)],
#  [(1, 0), (1, 0), (1, 0)]]

在 Python 3.X 中,您必须将其包装在 另一个 列表调用中,因为 map(...) 返回一个 map 对象。

cartesian_tuples = list(map(list, list(product(perms, repeat=3))))

或者,您可以避免所有这些废话并使用列表推导式。

cartesian_tuples = [[perm for perm in prod] for prod in product(perms, repeat=3)]

但每次需要时创建一个新的迭代器可能会更好。

def product_of_permutations(n, k):
    return product(permutations(range(k)), repeat=n)

【讨论】:

感谢您的帮助。我很感激。我在这个问题上犯了一个错误。请查看编辑。【参考方案2】:

考虑一下,可能有一种非常简单的方法可以使用itertools.combinationsset 获得所需的结果:

import itertools
K = 2
N = 3
perms = list(itertools.permutations(range(K), K))
# The order matters so we need to copy the list N times
perms = perms*N 
# Create the combinations
combs = itertools.combinations(perms, N)
# Only keep unique combinations
M = set(combs)

如果您想将其作为列表使用:

M = [list(i) for i in M]

然后返回

[[(1, 0), (0, 1), (0, 1)],
 [(1, 0), (1, 0), (1, 0)],
 [(0, 1), (0, 1), (1, 0)],
 [(0, 1), (1, 0), (1, 0)],
 [(0, 1), (0, 1), (0, 1)],
 [(0, 1), (1, 0), (0, 1)],
 [(1, 0), (0, 1), (1, 0)],
 [(1, 0), (1, 0), (0, 1)]]

【讨论】:

感谢您的帮助。我很感激。我在这个问题上犯了一个错误。请查看编辑。

以上是关于如何从所有排列中生成所有可能的组合?的主要内容,如果未能解决你的问题,请参考以下文章

按位移位以在 C 中生成所有可能的排列 [重复]

Hive UDF 从列表中生成所有可能的有序组合

如何在字典中生成所有可能的组合

ruby - 如何从字符串数组中生成可能的字母顺序组合?

Javascript - 在单个数组中生成所有元素组合(成对)

如何在 R 中生成对象的排列或组合?