2 ^ n具有高级过滤功能的Itertools组合

时间:2016-03-24 23:26:25

标签: python set combinations permutation

我知道我可以使用itertools抽出组合,并定义组合组的大小,如下所示:

import itertools
print list(itertools.combinations(['V','M','T','O','Q','K','D','R'], 4))

这个输出就像一个元组列表,在这种情况下长度为4。

从这里,我想要做的是强制执行2个参数 - 1)排除包含某些对的任何组合/元组 - 例如V和M,或Q和K. 2)强制每个元组仅包含1个字母的实例。我相信itertools已经在做#2。

应该保留的只是那些不包含任何这些预先确定的“错误”对的元组。因此,如果我排除了包含V和M的群组,则群组('V','M','Q','D')将无效,但('V','R','Q','D')将有效。

对我来说,最好的方法是什么?

3 个答案:

答案 0 :(得分:3)

您可以定义验证功能并使用

进行过滤
>>> import itertools
>>> def is_valid(data):
        if 'V' in data and 'M' in data:
            return False
        if 'Q' in data and 'K' in data:
            return False
        return True

>>> filter(is_valid,itertools.combinations('VMTOQKDR', 4))
[('V', 'T', 'O', 'Q'), ('V', 'T', 'O', 'K'), ('V', 'T', 'O', 'D'), ('V', 'T', 'O', 'R'), ('V', 'T', 'Q', 'D'), ('V', 'T', 'Q', 'R'), ('V', 'T', 'K', 'D'), ('V', 'T', 'K', 'R'), ('V', 'T', 'D', 'R'), ('V', 'O', 'Q', 'D'), ('V', 'O', 'Q', 'R'), ('V', 'O', 'K', 'D'), ('V', 'O', 'K', 'R'), ('V', 'O', 'D', 'R'), ('V', 'Q', 'D', 'R'), ('V', 'K', 'D', 'R'), ('M', 'T', 'O', 'Q'), ('M', 'T', 'O', 'K'), ('M', 'T', 'O', 'D'), ('M', 'T', 'O', 'R'), ('M', 'T', 'Q', 'D'), ('M', 'T', 'Q', 'R'), ('M', 'T', 'K', 'D'), ('M', 'T', 'K', 'R'), ('M', 'T', 'D', 'R'), ('M', 'O', 'Q', 'D'), ('M', 'O', 'Q', 'R'), ('M', 'O', 'K', 'D'), ('M', 'O', 'K', 'R'), ('M', 'O', 'D', 'R'), ('M', 'Q', 'D', 'R'), ('M', 'K', 'D', 'R'), ('T', 'O', 'Q', 'D'), ('T', 'O', 'Q', 'R'), ('T', 'O', 'K', 'D'), ('T', 'O', 'K', 'R'), ('T', 'O', 'D', 'R'), ('T', 'Q', 'D', 'R'), ('T', 'K', 'D', 'R'), ('O', 'Q', 'D', 'R'), ('O', 'K', 'D', 'R')]
>>> 

修改

为了使其更加灵活,您可以创建一个可以生成验证功能的函数,并将其与@PadraicCunningham的概念混合使用set

>>> import itertools
>>> def make_validator(*checks):
        checker=[set(x) for x in checks]
        def validator(data):
            return not any( st.issubset(data) for st in checker)
        return validator

>>> is_valid = make_validator("VM","QK")
>>> filter(is_valid, itertools.combinations('VMTOQKDR', 4))
[('V', 'T', 'O', 'Q'), ('V', 'T', 'O', 'K'), ('V', 'T', 'O', 'D'), ('V', 'T', 'O', 'R'), ('V', 'T', 'Q', 'D'), ('V', 'T', 'Q', 'R'), ('V', 'T', 'K', 'D'), ('V', 'T', 'K', 'R'), ('V', 'T', 'D', 'R'), ('V', 'O', 'Q', 'D'), ('V', 'O', 'Q', 'R'), ('V', 'O', 'K', 'D'), ('V', 'O', 'K', 'R'), ('V', 'O', 'D', 'R'), ('V', 'Q', 'D', 'R'), ('V', 'K', 'D', 'R'), ('M', 'T', 'O', 'Q'), ('M', 'T', 'O', 'K'), ('M', 'T', 'O', 'D'), ('M', 'T', 'O', 'R'), ('M', 'T', 'Q', 'D'), ('M', 'T', 'Q', 'R'), ('M', 'T', 'K', 'D'), ('M', 'T', 'K', 'R'), ('M', 'T', 'D', 'R'), ('M', 'O', 'Q', 'D'), ('M', 'O', 'Q', 'R'), ('M', 'O', 'K', 'D'), ('M', 'O', 'K', 'R'), ('M', 'O', 'D', 'R'), ('M', 'Q', 'D', 'R'), ('M', 'K', 'D', 'R'), ('T', 'O', 'Q', 'D'), ('T', 'O', 'Q', 'R'), ('T', 'O', 'K', 'D'), ('T', 'O', 'K', 'R'), ('T', 'O', 'D', 'R'), ('T', 'Q', 'D', 'R'), ('T', 'K', 'D', 'R'), ('O', 'Q', 'D', 'R'), ('O', 'K', 'D', 'R')]
>>> filter(make_validator("VM","QK",'MT',"DR"), itertools.combinations('VMTOQKDR', 4))
[('V', 'T', 'O', 'Q'), ('V', 'T', 'O', 'K'), ('V', 'T', 'O', 'D'), ('V', 'T', 'O', 'R'), ('V', 'T', 'Q', 'D'), ('V', 'T', 'Q', 'R'), ('V', 'T', 'K', 'D'), ('V', 'T', 'K', 'R'), ('V', 'O', 'Q', 'D'), ('V', 'O', 'Q', 'R'), ('V', 'O', 'K', 'D'), ('V', 'O', 'K', 'R'), ('M', 'O', 'Q', 'D'), ('M', 'O', 'Q', 'R'), ('M', 'O', 'K', 'D'), ('M', 'O', 'K', 'R'), ('T', 'O', 'Q', 'D'), ('T', 'O', 'Q', 'R'), ('T', 'O', 'K', 'D'), ('T', 'O', 'K', 'R')]
>>> 

make_validator将您不想要的任意数量的排除组合作为参数,并创建一个执行检查并返回它的函数;您可以将结果保存在变量中或直接使用

答案 1 :(得分:1)

我会过滤一套:

import itertools
c = itertools.combinations(['V','M','T','O','Q','K','D','R'], 4)

st = {"V","M"}

print([co for co in c if not st.issubset(co)])

如果你想过滤两个:

st1 = {"V","M"}
st2 = {"Q","K"}

print([co for co in c if not st1.issubset(co) and not st2.issubset(co)])

如果你有两个以上,那么使用any可能会更好:

sts = [{"V","M"},{"V","R"},{"T","O"}]

print([co for co in c if not any(st.issubset(co) for st in sts)])

禁止你自己组合逻辑,你不能避免创建所有组合和过滤,即使你自己滚动你在纯python中做它可能会慢一点你有一个大数据集

答案 2 :(得分:0)

您可以使用if条件的列表推导:

>>> [x for x in itertools.combinations('VMTOQKDR', 4) 
       if not (('V' in x and 'M' in x) or ('Q' in x and 'K' in x))]
[('V', 'T', 'O', 'Q'),
 ('V', 'T', 'O', 'K'),
 ... 37 more ...
 ('O', 'Q', 'D', 'R'),
 ('O', 'K', 'D', 'R')]

但请注意,这仍然会通过所有组合,只是“扔掉”无效的组合。例如,如果前两个元素是('V','M'),它将继续生成`('V','M','O','R')并扔掉它,依此类推。对于在这种情况下生成的组合数量,这不是问题。对于较大的组合,您可能希望使用自定义递归算法提前丢弃无效的部分结果。