【问题标题】:How to filter elements of Cartesian product following specific ordering conditions如何根据特定的订购条件过滤笛卡尔积的元素
【发布时间】:2019-04-03 07:43:37
【问题描述】:

我必须生成具有不同变量的多个反应。它们有 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()

【问题讨论】:

  • 然后拆分字母和数字,将数字存储在列表中,并确保列表是降序的。如果不是这种情况,请删除示例
  • 它不是很大,为什么不使用 3 个简单的嵌套循环呢?

标签: python cartesian-product


【解决方案1】:

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

【讨论】:

  • 为什么不for s in range(b)
  • 我认为是 h > s。但他没有给出明确的例子。
  • @mik 很好的建议,但由于range 的专属上限是 range(1,b+1)
  • 当然,并且允许 B5 范围应该到 6
【解决方案2】:

Patrick 以列表理解方式回答

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

【讨论】:

    【解决方案3】:

    我将按照以下方式实施您的“使用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 个tuples 中的list,每个拥有 3 个ints。所以你需要使用所谓的 f-string 来制作 strs :

    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-string。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-05-06
      相关资源
      最近更新 更多