为每个索引生成具有单独限制的所有排列

时间:2018-07-26 22:00:13

标签: python list generator permutation

假设我们有一个列表,例如[3, 2, 1]。我想以以下形式生成该列表的所有排列:

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

用于任何长度为n的列表。这样,原始列表的第i个元素的值就是所有排列中第i个元素的值的上限。

由于输入列表可能非常大(例如yield),因此我还想使用使用n = 30的生成器。

到目前为止,我一直在使用这样的东西:

itertools.product(range(1, 5), repeat=5)

for循环中使用以下输出:

(1, 1, 1, 1, 1), (1, 1, 1, 1, 2), (1, 1, 1, 1, 3), (1, 1, 1, 1, 4), (1, 1, 1, 2, 1), (1, 1, 1, 2, 2), (1, 1, 1, 2, 3), ... 

但是,我认为它不允许为排列的每个元素指定自定义限制。

另外,请注意,输入列表的元素不一定必须是连续数字,因此[25, 17, 10, 4]是有效的输入。

3 个答案:

答案 0 :(得分:1)

您可以过滤itertools.product

的结果
>>> from itertools import product
>>> l = [3,2,1]
>>> list(filter(lambda t: all(x<=y for x,y in zip(t,l)), product(l, repeat=len(l))))
[(3, 2, 1), (3, 1, 1), (2, 2, 1), (2, 1, 1), (1, 2, 1), (1, 1, 1)]

答案 1 :(得分:1)

此递归函数按所需顺序返回生成器:

def f(limits):
    if not limits:
        yield ()
        return

    for l in f(limits[1:]):
        for i in range(1, limits[0]+1):
            yield (i,) + l

>>> print(list(f([3, 2, 1])))
[(1, 1, 1), (2, 1, 1), (3, 1, 1), (1, 2, 1), (2, 2, 1), (3, 2, 1)]

答案 2 :(得分:0)

您正在寻找一系列范围的笛卡尔积,其参数由您的输入列表定义:

from itertools import product
lims = [3, 2, 1]
gen = product(*(range(1,lim+1) for lim in lims))
print(list(gen))

结果是

[(1, 1, 1), (1, 2, 1), (2, 1, 1), (2, 2, 1), (3, 1, 1), (3, 2, 1)]