如何有效地生成和过滤列表产品列表的所有组合

时间:2019-03-28 10:26:05

标签: python python-3.x

您好,这里是问题。我在输入[[1,2,3],[4,5,6],[7,8,9]]等中有类似的内容

我想生成这些列表的乘积的所有可能组合,然后将它们之间的结果组合的每个元素相乘,最后以一个间隔过滤结果。

所以首先输入一个n列表[[1,2,3],[4,5,6],[7,8,9],[10,11,12]] ...等等

然后将给(1,4,7,10)                      (1、4、7、11)                      (1、4、7、12) 等等

然后将这些结果组合为n中的k,如第一行的(1,4,7)(1,4,10)(1,7,10)

x的相乘为1 * 4 * 7 = 28,1 * 4 * 10 = 40,1 * 7 * 10 = 70

然后从中仅获得唯一的组合以及在预先选择的时间间隔内需要的结果:如果x> 50和x <100,我将得到(1,7,10):70

我确实尝试过

    def mult(lst):                 #A function mult i'm using later
        r = 1
        for element in lst:
           r *= element
        return round(r)

    s = []                                #Where i add my list of list
    for i in range(int(input1)):
        b = input("This is line %s : " % (i+1)).split()
        for i in range(len(b)):
           b[i] = float(b[i]) 
        s.append(b)

    low_result = input("Expected low_result : ")
    high_result = input("Expected high_result : ")

    combine = []
    my_list = []

    for element in itertools.product(*s):
       l= [float(x) for x in element]
       comb = itertools.combinations([*l], int(input2))
       for i in list(comb):
          combine.append(i)
          res = mult(i)
          if res >= int(low_result) and res <= int(high_result):
             my_list.append(res) 
             f = open("list_result.txt","a+")
             f.write("%s : result is  %s\n" % (i, res))
             f.close()

它总是导致内存错误,原因是我要查找的内容太多了。

我想要的是一种从20个或更多个元素的列表中生成所有乘积以及k对应n在k中所需要的结果(间隔)的方法。

1 个答案:

答案 0 :(得分:1)

如上所述,我认为可以通过不随时将数组保存在内存中而无需增加内存的方式来完成此操作。但是主要的问题是运行时。

数学

我们写的是:

  • 产生m个项目n的{​​{1}}行的每种组合
  • 然后从这些n ** mc中选择m个项目

这非常大。如果我们有C(m, c)行,每行m=25个项目,然后选择其中的n=3个项目,我们将得到:

如果相反,我们:

  • = 1.948763802×10¹⁵行中选择c行:m和以前一样
  • 然后从以下C(m, c)行中选择n项的每种组合:c

使用n ** c行,每行m=25个项目,然后选择其中的n=3个项目,我们得到:

  • = c=3
  • = n ** c * C(m, c)
  • = 3 ** 3 * 2300

现在这是一个可以解决的问题。

代码

20700

此解决方案也不会返回重复的答案(除非同一值出现在多行中)。

作为一种优化,如果我们检测到结果太大或太小,乘法方法将尝试尽早返回。我们也只打开文件一次,然后在行中不断添加行。

进一步优化

您还可以通过筛选出无法解决问题的值来提前优化一组值。但是对于较小的from itertools import product, combinations def mult(values, min_value, max_value): """ Multiply together the values, but return None if we get too big or too small """ output = 1 for value in values: output *= value # Early return if we go too big if output > max_value: return None # Early return if we goto zero (from which we never return) if output == 0 and min_value != 0: return None if output < min_value: return None return output def yield_valid_combos(values, choose, min_value, max_value): # No doubt an even fancier list compression would get this too for rows in combinations(values, choose): for combos in product(*rows): value = mult(combos, min_value, max_value) if value is not None: yield combos, value values = [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]] with open('list_result.txt', 'w') as fh: for selection, value in yield_valid_combos( values, choose=3, min_value=50, max_value=100): fh.write('{}: result is {}\n'.format(selection, value)) 值,您可能会发现甚至没有必要。

值的最小可能组合是每行最小值集中的c个项目。如果我们从一组最小值中选取c个最小项,将它们互斥在一起,然后将最大值除以该数字,它将为我们提供可在解决方案中获得的最大值的上限。然后,我们可以筛选出高于该值的所有值(减少排列)