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

How to filter elements of Cartesian product following specific ordering conditions

我必须用不同的变量生成多个反应。它们有 3 个元素。我们称它们为 BSH。它们都以 B1 开头。如果至少有一个 B,则可以将 S 附加到元素。所以它可以是 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()

简单的 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 指出改进。

帕特里克以列表理解方式回答

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']    

我会按照以下方式实施您的 "use itertools.product and get rid off unnecessary elements" 解决方案:

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 现在是 list,共 35 tuples,每个持有 3 ints。所以你需要制作 strs 它们,例如使用所谓的 f-string:

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 字符串。