【发布时间】:2017-07-05 10:21:25
【问题描述】:
我需要一个函数,它通过重复一个可迭代的子句来生成所有排列,其中两个连续元素必须不同;例如
f([0,1],3).sort()==[(0,1,0),(1,0,1)]
#or
f([0,1],3).sort()==[[0,1,0],[1,0,1]]
#I don't need the elements in the list to be sorted.
#the elements of the return can be tuples or lists, it doesn't change anything
不幸的是 itertools.permutation 不能满足我的需要(迭代中的每个元素在返回中出现一次或不出现)
我尝试了很多定义;首先,从 itertools.product(iterable,repeat=r) 输入中过滤元素,但对于我需要的东西来说太慢了。
from itertools import product
def crp0(iterable,r):
l=[]
for f in product(iterable,repeat=r):
#print(f)
b=True
last=None #supposing no element of the iterable is None, which is fine for me
for element in f:
if element==last:
b=False
break
last=element
if b: l.append(f)
return l
其次,我尝试为循环构建 r,一个在另一个内部(其中 r 是排列的类,在数学中表示为 k)。
def crp2(iterable,r):
a=list(range(0,r))
s="\n"
tab=" " #4 spaces
l=[]
for i in a:
s+=(2*i*tab+"for a["+str(i)+"] in iterable:\n"+
(2*i+1)*tab+"if "+str(i)+"==0 or a["+str(i)+"]!=a["+str(i-1)+"]:\n")
s+=(2*i+2)*tab+"l.append(a.copy())"
exec(s)
return l
我知道,你不需要记住我:exec 丑陋,exec 可能很危险,exec 不容易阅读……我知道。 为了更好地理解该功能,我建议您将 exec(s) 替换为 print(s)。
我给你一个例子,说明 crp([0,1],2) 的 exec 中的字符串是什么:
for a[0] in iterable:
if 0==0 or a[0]!=a[-1]:
for a[1] in iterable:
if 1==0 or a[1]!=a[0]:
l.append(a.copy())
但是,除了使用 exec,我还需要更好的函数,因为 crp2 仍然太慢(即使比 crp0 快);有什么方法可以在不使用 exec 的情况下用 r 重新创建代码?还有其他方法可以做我需要的吗?
【问题讨论】:
-
顺便说一句,你想要的不是“重复排列”。
-
@EricDuminil 我知道,但最接近我需要的操作是结合重复
-
是的,但与排列无关。
-
正如我在回答中所说,这个问题大于排列(允许一些重复)但小于重复的产品(不允许一些重复)。我不知道什么是好名字,所以我只是称它们为产品。
标签: python algorithm combinations permutation