如何根据特定订购条件过滤笛卡尔积的元素

时间:2019-04-03 07:43:38

标签: python cartesian-product

我必须生成多个具有不同变量的反应。他们有3个元素。我们称它们为BSH。它们都以B1开头。如果至少有一个S,可以将B附加到元素上。因此可以是B1S1B2S2B2S1等...但不能是B1S2H也是如此。 B1S1H1B2S2H1B4S1H1,但永远不会B2S2H3。最终的变化将是B5S5H5。我尝试了itertools.product。但是我不知道如何清除不符合我的条件的元素,以及如何添加下一个元素。这是我的代码:

import itertools

a = list(itertools.product([1, 2, 3, 4], repeat=4))

#print (a)

met = open('random_dat.dat', 'w')
met.write('Reactions')
met.write('\n')
for i in range(1,256): 
    met.write('\n')
    met.write('%s: B%sS%sH%s -> B%sS%sH%s' %(i, a[i][3], a[i][2], a[i][1], a[i][3], a[i][2], a[i][1]))
    met.write('\n')
met.close()

3 个答案:

答案 0 :(得分:4)

简单的for循环将满足您的要求:

bsh = []
for b in range(1,6):
    for s in range(1,b+1):
        for h in range(1,b+1):
            bsh.append( f"B{b}S{s}H{h}" )

print(bsh)                

输出:

['B1S1H1', 'B2S1H1', 'B2S1H2', 'B2S2H1', 'B2S2H2', 'B3S1H1', 'B3S1H2', 'B3S1H3', 
 'B3S2H1', 'B3S2H2', 'B3S2H3', 'B3S3H1', 'B3S3H2', 'B3S3H3', 'B4S1H1', 'B4S1H2', 
 'B4S1H3', 'B4S1H4', 'B4S2H1', 'B4S2H2', 'B4S2H3', 'B4S2H4', 'B4S3H1', 'B4S3H2', 
 'B4S3H3', 'B4S3H4', 'B4S4H1', 'B4S4H2', 'B4S4H3', 'B4S4H4', 'B5S1H1', 'B5S1H2', 
 'B5S1H3', 'B5S1H4', 'B5S1H5', 'B5S2H1', 'B5S2H2', 'B5S2H3', 'B5S2H4', 'B5S2H5', 
 'B5S3H1', 'B5S3H2', 'B5S3H3', 'B5S3H4', 'B5S3H5', 'B5S4H1', 'B5S4H2', 'B5S4H3', 
 'B5S4H4', 'B5S4H5', 'B5S5H1', 'B5S5H2', 'B5S5H3', 'B5S5H4', 'B5S5H5']

感谢@mikuszefski指出改进之处。

答案 1 :(得分:0)

以列表理解方式来修饰他的答案

bsh = [f"B{b}S{s}H{h}" for b in range(1,5) for s in range(1,b+1) for h in range(1,b+1)] 

给予

['B1S1H1',
 'B2S1H1',
 'B2S1H2',
 'B2S2H1',
 'B2S2H2',
 'B3S1H1',
 'B3S1H2',
 'B3S1H3',
 'B3S2H1',
 'B3S2H2',
 'B3S2H3',
 'B3S3H1',
 'B3S3H2',
 'B3S3H3',
 'B4S1H1',
 'B4S1H2',
 'B4S1H3',
 'B4S1H4',
 'B4S2H1',
 'B4S2H2',
 'B4S2H3',
 'B4S2H4',
 'B4S3H1',
 'B4S3H2',
 'B4S3H3',
 'B4S3H4',
 'B4S4H1',
 'B4S4H2',
 'B4S4H3',
 'B4S4H4']    

答案 2 :(得分:0)

我将通过以下方式实现您的“使用itertools.product并摆脱不必要的元素”解决方案:

import itertools
a = list(itertools.product([1,2,3,4,5],repeat=3))
a = [i for i in a if (i[1]<=i[0] and i[2]<=i[1] and i[2]<=i[0])]

请注意,我假设最后一个元素必须小于或等于任何其他元素。请注意,a现在是35个list中的tuple个,每个拥有3个int。因此,您需要使用所谓的f字符串来制作str个,例如:

a = [f"B{i[0]}S{i[1]}H{i[2]}" for i in a]
print(a)

输出:

['B1S1H1', 'B2S1H1', 'B2S2H1', 'B2S2H2', 'B3S1H1', 'B3S2H1', 'B3S2H2', 'B3S3H1', 'B3S3H2', 'B3S3H3', 'B4S1H1', 'B4S2H1', 'B4S2H2', 'B4S3H1', 'B4S3H2', 'B4S3H3', 'B4S4H1', 'B4S4H2', 'B4S4H3', 'B4S4H4', 'B5S1H1', 'B5S2H1', 'B5S2H2', 'B5S3H1', 'B5S3H2', 'B5S3H3', 'B5S4H1', 'B5S4H2', 'B5S4H3', 'B5S4H4', 'B5S5H1', 'B5S5H2', 'B5S5H3', 'B5S5H4', 'B5S5H5']

但是,如果您愿意,也可以使用其他格式化方法代替f字符串。