4

找到 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]。

4

2 回答 2

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))
于 2013-07-21T23:26:58.610 回答
0

我想我已经想出了一个解决方案,但如果这个错误,请纠正我。我也很想看看是否有更优雅的解决方案。

首先,我想出了组合的总数。所有没有替换的组合都等于 n!/r!(nr)! 并且替换等于 (m+s-1)!/s!(m-1)! 其中 m 和 n 是可供选择的项目数,r 和 s 是您实际选择的项目数。因为我知道每个组合中我想要的总项目(我们称之为上限),我找到了无替换类型(n=0)的 0 和替换类型的“上限”(m=3)的组合数并将这些数字相乘。然后,将无替换类型 (n=1) 的 1 的组合数乘以替换类型 (m=2) 的组合“cap-1”。这样做直到您最终添加了无替换类型(n = 3)乘以替换类型(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替换组合包括在我的列表中。我希望对此有任何反馈,特别是如果有更好的解决方案,或者如果它不像我认为的那样有效。谢谢!

于 2013-07-21T23:16:58.910 回答