itertools cominbations替换有限制

时间:2015-09-22 02:46:01

标签: python itertools

是否有更好的方法列出所有可能的替换组合,每个元素的最小和最大出现次数,而不是(1)列出所有可能的组合,没有这些限制itertools.combinations_with_replacement()然后(2) )逐个检查结果,看看它们是否符合限制条件?

作为一个例子,假设我有一个数组[a b c],我想要绘制10次,但我想看到每个元素至少1次,但不超过一半的时间(即5次),我不想看到以下

b b b b b c c c c c # no a
a a a a a a b b c c # a more than 5 times

我的真实数组更大,有20个元素可以从...中抽取100次。

提前致谢

编辑:

这是我尝试的内容,但显然我的20个元素被抽取100次似乎效率不高......

a = []
for c in list(itertools.combinations_with_replacement(range(4), 10)):
    valid = 1
    for i in range(4):
        if not c.count(i) or c.count(i) > 5:
            valid = 0
            break
    if valid:
        a.append(c)

我真正要做的是我有20个项目,我想弄清楚我可以从中产生的所有可能的篮子,比例为增量整数(即1%,2%等,没有1.5%),因此100倍加起来达到100%。应始终显示每个项目,但它们都不应超过50%......

2 个答案:

答案 0 :(得分:2)

这是我根据您发布的方法提出的建议:

至少查看一次所有元素:您可以从填充了一组元素的结果数组开始。

从这样的"种子"开始在某种程度上限制了检查和消除重复的组合数量;它还简化了检查。

import itertools
a = []
seed = (0,1,2,3)
for c in itertools.combinations_with_replacement(range(4), 6):
    valid = True
    for i in range(4):
        if c.count(i) > 4:
            valid = False
            break
    if valid:
        a.append(c+seed)
a

您可以创建一个生成器表达式(基于相同的原理):

import itertools
from collections import Counter
a = ((0,1,2,3) + c for c in itertools.combinations_with_replacement(range(4), 6) if max(Counter(c).values()) < 5)

答案 1 :(得分:1)

您对实际要求的描述表明了一种即时,有效且简单(虽然不优雅)的解决方案。

首先想象你没有少于50的要求:

只需使用19个嵌套for循环。外部循环从1到81循环,下一个从1到82减去第一个,依此类推。最后一个数字最多填充100个。

要添加低于50%的要求,如果小于上面计算的数量,则需要使循环停止在50。如果最终数字大于50,他们也需要开始更高。

这将是非常有效和直接的 - 它将只生成你想要的那些。它可以重写为使用变量而不是固定的20,但这会使它变得相当复杂。

然而,user2357112的要点很好,并且通过这个简单的公式强调了这一点。这里组合数量的粗略估计显着大于2e13。这种蛮力方法不太可行。您可能需要对基础问题采用更复杂的方法。