在过滤过程中,您使用一对一检查。因此,但从那时起,当存在三个以上的元素时,这将
无法运作。
这是因为您可以
在多次(真实)交换之后获得相同的排列。例如:
[1 ,2(1),2(2),3 ] -> swap 1 with 3
[1 ,3, 2(2),2(1)] -> swap 1 with 2
[1 ,2(2),3 ,2(1)] -> swap 2 with 3
[1 ,2(2),2(1),3 ]
正如您所看到的,排列是相同的(但两个“二”的起源不同)。 因此,我们间接交换了这两个“二”。
尽管如此,没有必要使它那么复杂。 这里有两种方法可能会起作用:
- 对列表进行排序,并强制执行一个约束条件,即您只能发出字典顺序更高的先前列表; 和
- 首先计算出现次数(使用Counter),然后确保您基于计数器发出。
后者将运行得更快,因为它不会生成必须省略的排列。
一个示例实现可能是:
from collections import Counter
def f(lst):
def g(l,c,n):
if n <= 0:
yield tuple(l)
else:
for k,v in c.items():
if v > 0:
c[k] -= 1
l.append(k)
for cfg in g(l,c,n-1):
yield cfg
l.pop()
c[k] += 1
for cfg in g([],Counter(lst),len(lst)):
yield cfg
这将给出:
>>> list(f([1,1,2,2]))
[(1, 1, 2, 2), (1, 2, 1, 2), (1, 2, 2, 1), (2, 1, 1, 2), (2, 1, 2, 1), (2, 2, 1, 1)]
>>> list(f([1,1,2,2,3]))
[(1, 1, 2, 2, 3), (1, 1, 2, 3, 2), (1, 1, 3, 2, 2), (1, 2, 1, 2, 3), (1, 2, 1, 3, 2), (1, 2, 2, 1, 3), (1, 2, 2, 3, 1), (1, 2, 3, 1, 2), (1, 2, 3, 2, 1), (1, 3, 1, 2, 2), (1, 3, 2, 1, 2), (1, 3, 2, 2, 1), (2, 1, 1, 2, 3), (2, 1, 1, 3, 2), (2, 1, 2, 1, 3), (2, 1, 2, 3, 1), (2, 1, 3, 1, 2), (2, 1, 3, 2, 1), (2, 2, 1, 1, 3), (2, 2, 1, 3, 1), (2, 2, 3, 1, 1), (2, 3, 1, 1, 2), (2, 3, 1, 2, 1), (2, 3, 2, 1, 1), (3, 1, 1, 2, 2), (3, 1, 2, 1, 2), (3, 1, 2, 2, 1), (3, 2, 1, 1, 2), (3, 2, 1, 2, 1), (3, 2, 2, 1, 1)]
A = [2,2,1,1]
,在函数f
中,你还将调用f([2,1,2,1], 1, len(A))
,两种情况都可以输出[2,2,1,1]
(第一种情况没有排列,第二种情况将索引1和2之间的元素进行排列)。 - Nuageux