是否有itertools.permutations模式

时间:2019-12-28 13:55:34

标签: python itertools

当我遍历itertools.permutations时,我想知道特定的数字组合会显示在哪些索引上,而不会缓慢地遍历整个事物。

例如:

当我有一个列表foo,它等于list(itertools.permutations(range(10)))时,我想知道第一个字符在哪个索引处为零,而第十七个字符在三个索引处。一种简单的方法是检查每种组合,看看是否符合我的要求。

n = 10
foo = list(itertools.permutations(range(n)))
solutions = []

for i, permutation in foo:
    if permutation[0] == 0 and permutation[16] == 3:
        solutions.append(i)

但是,随着n变大,它变得非常慢,并且内存效率非常低。

我是否可以使用某种模式,而不是创建一个长列表,我可以简单地说,如果(a*i+b)%c == 0那么我就知道它会适合我的模式。

编辑:实际上,我将有许多条件,其中一些条件也涉及两个以上的职位,因此,我希望通过组合这些条件,我可以将可能性的数量限制到可行的程度。另外,100可能很大,我希望n不会大于20。

1 个答案:

答案 0 :(得分:1)

您需要在非固定元素的排列与已注册固定单元格的对应排列之间进行映射。例如,如果您对列表[0, 1, 2, 3, 4]上的排列进行计数,并要求零单元格的值为1,第三单元格的值为2,则排列(0, 4, 3)将映射到(1, 0, 4, 2, 3)。我知道,元组在这种情况下不友好,因为它们是不可变的,但是列表具有insert方法,在这里非常有用。这就是为什么我将它们转换为列表,然后返回到元组的原因。

import itertools

def item_padding(item, cells):
    #returns padding of item, e.g. (0, 4, 3) -> (1, 0, 4, 2, 3)
    listed_item = list(item)
    for idx in sorted(cells):
        listed_item.insert(idx, cells[idx])
    return tuple(listed_item)

array = range(5)
cells = {0:1, 3:2} #indexes and their fixed values
remaining_items = set(list(array)) - set(list(cells.values()))
print(list(map(lambda x: item_padding(x, cells), itertools.permutations(remaining_items))))

输出:

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

总而言之,列表转换和迭代都非常慢。尽管如此,我认为该算法在概念上是一个很好的示例,它揭示了可以在此处执行的操作。如果您确实需要对其进行优化,请改用numpy

更新:

如果arrayrange(12)(排列3628800),则在笔记本电脑上可以工作6秒钟。这比返回未填充的元组要多三倍。