Python - 有遗漏的新排列列表

Python - New list of permutations with omissions

假设我有一个值列表

my_list = [1,2,3,4]

我使用 itertools.permutations 来查找此列表的所有组合

perms = itertools.permutations(my_list)

创建

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

我开始对此进行迭代,发现我不再需要 perms 中以 (4,1...(3,1....

开头的任何项目

我如何重新创建包含这些特定遗漏的列表?遍历和删除项目是不可行的,因为这需要扩展到非常大的尺寸。

编辑:为澄清起见,(4,1,2,3) 应删除,因为它以 (4,1...) 开头,但不应该删除 (4,2,1,3),因为它以 (4,2...).

开头

您可以使用列表理解来获得预期的排列:

>>> [i for i in perms if i[0] not in {3,4}]
[(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1)]

请注意,使用 set 容器检查 membership.and 的时间复杂度为 O(1),如果您有更多过滤器编号,效率会更高!

如果你不想要以 3,14,1 开头的元组,你可以简单地做:

>>> perms = it.permutations(my_list)
>>> [i for i in perms if i[:2] !=[4,1] and i[:2] !=[4,1]]
[(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1), (3, 1, 2, 4), (3, 1, 4, 2), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1), (4, 1, 2, 3), (4, 1, 3, 2), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)]
>>> 
>>> from itertools import permutations
>>> my_list = [1,2,3,4]
>>> perms = permutations(my_list)
>>> perms
<itertools.permutations object at 0x107a63ad0>
>>> perms = filter(lambda x: x[:2] != (4,1) and x[:2] != (3,1), perms)
>>> perms
[(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)]

既然你说

Iterating through and removing items is not viable as this needs to scale to very large sizes.

最好的方法是包装由 permutations 生成的交互器,它将生成您想要的元组并跳过您不需要的元组:

my_list = [1,2,3,4]

def my_perms(my_list, f):
    for e in permutations(my_list):
        if f(e):
            yield e 

>>> list(my_perms(my_list, lambda t: t[:2] not in {(4,1), (3,1)}))
[(1, 2, 3, 4), (1, 2, 4, 3), (1, 3, 2, 4), (1, 3, 4, 2), (1, 4, 2, 3), (1, 4, 3, 2), (2, 1, 3, 4), (2, 1, 4, 3), (2, 3, 1, 4), (2, 3, 4, 1), (2, 4, 1, 3), (2, 4, 3, 1), (3, 2, 1, 4), (3, 2, 4, 1), (3, 4, 1, 2), (3, 4, 2, 1), (4, 2, 1, 3), (4, 2, 3, 1), (4, 3, 1, 2), (4, 3, 2, 1)]

或者,使用 ifilter from itertools:

>>> list(ifilter(lambda t: t[:2] not in {(4,1), (3,1)}, permutations(my_list)))

或者,直接在 Python 3+ 上过滤,因为这也会创建一个迭代器,而不是像在 Python 2 上过滤那样创建列表。