未订购的组合,有限的替换品

时间:2018-05-25 09:40:57

标签: python combinations itertools

我必须列出有限重复的无序组合 即对于给定的唯一元素列表,例如card_set创建长度为combo_len的所有组合,其元素重复为max repeat_limit次

以下代码适用于combo_len = 3和repeat_limit = 2,其中card_set = range(5)

注意我需要无序组合。 即(0,0,1)和(0,1,0)是相同的,所以下面的解决方案链接不满足我的条件

This帖子告诉我如何获得有限重复的提示组合

import itertools
import pprint
card_set = list(range(5))
a = sorted(set(itertools.combinations_with_replacement(card_set,3)))
neg = [(i,i,i) for i in card_set]
b = set(a) - set(neg)
print('a###')
pprint.pprint(a)
print('b###')
pprint.pprint(b)

上面的代码给出了一个有限的2个重复的无序组合,即。 neg包含不需要的重复(0,0,0)(1,1,1)等 所以     b = set(a) - set(neg) 给我所需的一套

对于combo_len = 3和repeat_limit = 2,上述代码有效。如何为范围(13)combo_len = 7和repeat_limit = 4

创建代码

输出:

a###
[(0, 0, 0),
 (0, 0, 1),
 (0, 0, 2),
 (0, 0, 3),
 (0, 0, 4),
 (0, 1, 1),
 (0, 1, 2),
 (0, 1, 3),
 (0, 1, 4),
 (0, 2, 2),
 (0, 2, 3),
 (0, 2, 4),
 (0, 3, 3),
 (0, 3, 4),
 (0, 4, 4),
 (1, 1, 1),
 (1, 1, 2),
 (1, 1, 3),
 (1, 1, 4),
 (1, 2, 2),
 (1, 2, 3),
 (1, 2, 4),
 (1, 3, 3),
 (1, 3, 4),
 (1, 4, 4),
 (2, 2, 2),
 (2, 2, 3),
 (2, 2, 4),
 (2, 3, 3),
 (2, 3, 4),
 (2, 4, 4),
 (3, 3, 3),
 (3, 3, 4),
 (3, 4, 4),
 (4, 4, 4)]
b###
{(0, 0, 1),
 (0, 0, 2),
 (0, 0, 3),
 (0, 0, 4),
 (0, 1, 1),
 (0, 1, 2),
 (0, 1, 3),
 (0, 1, 4),
 (0, 2, 2),
 (0, 2, 3),
 (0, 2, 4),
 (0, 3, 3),
 (0, 3, 4),
 (0, 4, 4),
 (1, 1, 2),
 (1, 1, 3),
 (1, 1, 4),
 (1, 2, 2),
 (1, 2, 3),
 (1, 2, 4),
 (1, 3, 3),
 (1, 3, 4),
 (1, 4, 4),
 (2, 2, 3),
 (2, 2, 4),
 (2, 3, 3),
 (2, 3, 4),
 (2, 4, 4),
 (3, 3, 4),
 (3, 4, 4)}

2 个答案:

答案 0 :(得分:1)

您可以使用Counter模块中的collections类来查找给定元组中每个值的重复次数。对于每个元组,创建一个Counter并检查重复的最大值。如果该最大值足够小,则接受元组;否则,拒绝它。

这是执行此操作的例程。如果我有更多的时间,我会很高兴。

小心这个例程。对于给定的range_size=13, combo_len=7, repeat_limit=4值,结果是长度为49,205的列表。

from collections import Counter
from itertools import combinations_with_replacement

def unordered_combinations_with_limited_replacements(
        range_size, combo_len, repeat_limit):
    return [t for t in combinations_with_replacement(range(range_size), combo_len)
            if max(Counter(t).values()) <= repeat_limit]

print(unordered_combinations_with_limited_replacements(5, 3, 2))
print(len(unordered_combinations_with_limited_replacements(13, 7, 4)))

这是打印输出:

[(0, 0, 1), (0, 0, 2), (0, 0, 3), (0, 0, 4), (0, 1, 1), (0, 1, 2), (0, 1, 3), (0, 1, 4), (0, 2, 2), (0, 2, 3), (0, 2, 4), (0, 3, 3), (0, 3, 4), (0, 4, 4), (1, 1, 2), (1, 1, 3), (1, 1, 4), (1, 2, 2), (1, 2, 3), (1, 2, 4), (1, 3, 3), (1, 3, 4), (1, 4, 4), (2, 2, 3), (2, 2, 4), (2, 3, 3), (2, 3, 4), (2, 4, 4), (3, 3, 4), (3, 4, 4)]
49205

答案 1 :(得分:0)

首先,示例代码中使用的neg仅在repeat_limit等于combo_length时才有效。

所以我搜索了一些可以计算列表中不同元素的内容,并在Counter模块中提出了collections。下一步是使用简单的itertools.combinations_with_replacement循环迭代for创建的所有元素。如果Counter对象中最常见的元素高于repeat_limit,请从列表中删除该元素。

此代码适用于每个范围,combo_length和repeat_limit:

import itertools
from collections import Counter

def getUnorderedCombo(list_range, combo_len, repeat_lim):
    card_set = list(range(list_range))
    a = list(set(itertools.combinations_with_replacement(card_set,combo_len)))
    i = 0
    while i < len(a):
        c = Counter(a[i])
        if c.most_common(1)[0][1] > repeat_lim:
            del a[i]
            i -= 1
        i += 1
    return set(a)