itertools.permutations会根据其位置而不是其值来生成其元素被视为唯一的元素。所以基本上我想避免重复这样的事情:
itertools.permutations
>>> list(itertools.permutations([1, 1, 1])) [(1, 1, 1), (1, 1, 1), (1, 1, 1), (1, 1, 1), (1, 1, 1), (1, 1, 1)]
之后的过滤是不可能的,因为在我的情况下,排列的数量太大。
有人知道合适的算法吗?
非常感谢你!
编辑:
我基本上想要的是以下内容:
x = itertools.product((0, 1, 'x'), repeat=X) x = sorted(x, key=functools.partial(count_elements, elem='x'))
这是不可能的,因为sorted创建列表并且itertools.product的输出太大。
抱歉,我应该已经描述了实际问题。
class unique_element: def __init__(self,value,occurrences): self.value = value self.occurrences = occurrences def perm_unique(elements): eset=set(elements) listunique = [unique_element(i,elements.count(i)) for i in eset] u=len(elements) return perm_unique_helper(listunique,[0]*u,u-1) def perm_unique_helper(listunique,result_list,d): if d < 0: yield tuple(result_list) else: for i in listunique: if i.occurrences > 0: result_list[d]=i.value i.occurrences-=1 for g in perm_unique_helper(listunique,result_list,d-1): yield g i.occurrences+=1 a = list(perm_unique([1,1,2])) print(a)
结果:
[(2, 1, 1), (1, 2, 1), (1, 1, 2)]
编辑(这是如何工作的):
我将上面的程序改写得更长,但可读性更好。
我通常很难解释一些事情,但是让我尝试一下。为了理解它是如何工作的,你必须了解一个类似但更简单的程序,该程序将产生所有带有重复的排列。
def permutations_with_replacement(elements,n): return permutations_helper(elements,[0]*n,n-1)#this is generator def permutations_helper(elements,result_list,d): if d<0: yield tuple(result_list) else: for i in elements: result_list[d]=i all_permutations = permutations_helper(elements,result_list,d-1)#this is generator for g in all_permutations: yield g
这个程序显然要简单得多:d代表permutations_helper中的depth并具有两个功能。一个函数是递归算法的停止条件,另一个函数用于传递的结果列表。
我们不返回每个结果,而是产生它。如果没有功能/运算符,yield我们将不得不在停止条件时将结果推送到某个队列中。但是这样一来,一旦满足停止条件,结果就会通过所有堆栈传播到调用者。这样做的目的是 for g in perm_unique_helper(listunique,result_list,d-1): yield g使每个结果都传播给调用方。
for g in perm_unique_helper(listunique,result_list,d-1): yield g
回到原始程序:我们有一个唯一元素列表。在使用每个元素之前,我们必须检查仍有多少个元素可以推送到result_list上。使用此程序非常类似于permutations_with_replacement。不同之处在于,每个元素的重复次数不能超过perm_unique_helper中的重复次数。