找到2个列表的所有组合的最佳方法是什么,其中1个列表中的值可以重复,而在另一个列表中它们不能重复?现在,我可以获得重复列表的所有组合,如:
import itertools
rep = ['A','B','C', 'D']
norep = ['1','2','3','4']
for i in itertools.combinations_with_replacement(rep,4):
print i
我可以获得非重复列表的所有组合:
for i in itertool.combinations(norep,4):
print i
我可以得到两个列表的组合,就好像它们都是非重复的一样:
for i in itertools.product([0, 1], repeat=4):
print [(norep[j] if i else rep[j]) for j, i in enumerate(i)]
但是,我无法弄清楚如何获得重复和非重复列表的组合。我还想添加包含空值的组合,例如['A','1',Null]。
答案 0 :(得分:2)
这就是我得到的。非常接近你的:
from itertools import chain
from itertools import combinations
# Huge name!
from itertools import combinations_with_replacement as cwr
from itertools import starmap
from itertools import product
from operator import add
def _weird_combinations(rep, no_rep, n_from_rep, n_from_norep):
return starmap(add, product(cwr(rep, n_from_rep),
combinations(no_rep, n_from_norep)))
def weird_combinations(rep, no_rep, n):
rep, no_rep = list(rep), list(no_rep)
# Allow Nones in the output to represent drawing less than n elements.
# If either input has None in it, this will be confusing.
rep.append(None)
# We can't draw more elements from no_rep than it has.
# However, we can draw as many from rep as we want.
least_from_rep = max(0, n-len(no_rep))
return chain.from_iterable(
_weird_combinations(rep, no_rep, n_from_rep, n-n_from_rep)
for n_from_rep in xrange(least_from_rep, n+1))
答案 1 :(得分:0)
我想我已经提出了一个解决方案,但如果这个错误请纠正我。我也很想知道是否有更优雅的解决方案。
首先,我想出了组合的总数。没有替换的所有组合等于n!/ r!(n-r)!和替换等于(m + s-1)!/ s!(m-1)!其中m和n是可供选择的项目数,r和s是您实际选择的项目数。因为我知道每个组合中我想要的总项目(我们称之为上限),我找到了无替换类型(n = 0)的0和替换类型的“cap”的组合数(m = 3)并将这些数字相乘。然后,将无替换类型(n = 1)中的1的组合数加上替换类型的组合“cap-1”(m = 2)。这样做直到你最后添加了无替换类型(n = 3)的“cap”组合乘以替换类型的0(m = 0)(感谢@AndréNicolas)。组合数量的代码如下。
import itertools
from math import factorial as fact
norep = ['A','B','C']
rep = ['1','2','3']
cap = 3 #length of combinations, e.g. cap=3, combo1=123,combo2=A12,etc
combos = 0
for i in range(cap+1):
combnorep = fact(len(norep))/(fact(cap-i)*fact(len(norep)-(cap-i)))
combrep = fact(len(rep)+i-1)/(fact(i)*fact(len(rep)-1))
combos = combos + combnorep*combrep
print combos
对于此示例,组合的数量为38.接下来,我想打印所有组合。为此,我确定了所有替换的组合,所有替换,以及两者的任意组合,例如。 n = 0时,M = 3; n = 1时,m = 2时;等等。这就是我想出的:
for i in range(cap+1):
norepcomb = [j for j in itertools.combinations(norep,i)]
repcomb = [k for k in itertools.combinations_with_replacement(rep,cap-i)]
for l in itertools.product(norepcomb,repcomb):
print list(itertools.chain.from_iterable(l))
要包含none
,我只需在我的列表中添加none
即可获得替换组合。我想对此提出任何反馈意见,特别是如果有更好的解决方案,或者这样做不像我认为的那样。谢谢!