如何编写一个函数(生成器),它包含三个字母(l1
,l2
,l3
)和三个数字(n1
,n2
,n3
)并提供l1
出现n1
次,l2
n2
次和l3
n3
的所有可能组合倍。
例如:
for i in function('a', 2, 'b', 1, 'c', 0):
print(i)
给出:
aab
baa
aba
答案 0 :(得分:2)
使用itertools.permutations
,您只需要一个薄的包装器:
from itertools import permutations
def l_n_times(l1, n1, l2, n2, l3, n3):
return permutations(l1*n1 + l2*n2 + l3*n3)
演示:
>>> for item in set(l_n_times('a', 2, 'b', 1, 'c', 0)):
... print(''.join(item))
...
baa
aba
aab
permutations
已经返回了一个生成器,因此您自己没有使用yield
。
答案 1 :(得分:1)
在我看来itertools
在这里不会有太大帮助,尽管递归实现可能如下所示:
def combine(l1, n1, l2, n2, l3, n3):
counters = {l1: n1, l2: n2, l3: n3} # remaining characters to use
buf = [] # string under construction
def recur(depth):
if not depth: # we've reached the bottom
yield ''.join(buf)
return
# choosing next character
for s, c in counters.iteritems():
if not c: # this character is exhausted
continue
counters[s] -= 1
buf.append(s)
for val in recur(depth-1):
# going down recursively
yield val
# restore the state before trying next character
buf.pop()
counters[s] += 1
length = sum(counters.values())
return recur(length)
for s in combine('a', 2, 'b', 1, 'c', 0):
print s
答案 2 :(得分:0)
让我们承认您的数据结构如下:
letters = {'a': 2, 'b': 1, 'c': 0}
递归函数将是:
def r(letters, prefix = ''):
for k,v in letters.items():
if v > 0:
d = dict(letters)
d[k] = v - 1
for val in r(d, prefix + k):
yield val
if all(v == 0 for _, v in letters.items()):
yield prefix
没有重复,它确实使用了生成器。与简单的itertools调用相比,相当沉重。
答案 3 :(得分:0)
itertools的文档可以这样说;
combination()的代码也可以表示为在过滤条目之后排列()的子序列,其中元素不按排序顺序(根据它们在输入池中的位置):
由于我们希望所有组合都没有重复,我们只会强制执行严格的排序(即目前只有屈服值大于最大值);
这似乎就是这样;
def dfunc(l,n):
old=[]
for i in it.permutations(''.join(list(a*b for a,b in sorted(it.izip(l,n))))):
if i > old:
old=i
yield i
>>> dfunc(['b','c','a'],[1,0,2])
<generator object dfunc at 0x10ba055a0>
>>> list(dfunc(['b','c','a'],[1,0,2]))
[('a', 'a', 'b'), ('a', 'b', 'a'), ('b', 'a', 'a')]