Python,两个列表之间元素添加的所有组合,带约束

Python,两个列表之间元素添加的所有组合,带约束,python,list,loops,recursion,itertools,Python,List,Loops,Recursion,Itertools,我有两份清单: list1 = [1, 2, 3] list2 = [0.5, 1] 任务是通过将第二个列表中的变量添加到其元素中,从原始列表创建所有可能的组合: list1 = [1+0.5, 2, 3] list2 = [1, 2+0.5, 3] list3 = [1, 2, 3+0.5] list4 = [1+0.5, 2+0.5, 3] list5 = [1, 2+0.5, 3+0.5] list6 = [1+0.5, 2, 3+0.5] list7 = [1+0.5, 2+0.5,

我有两份清单:

list1 = [1, 2, 3]
list2 = [0.5, 1]
任务是通过将第二个列表中的变量添加到其元素中,从原始列表创建所有可能的组合:

list1 = [1+0.5, 2, 3]
list2 = [1, 2+0.5, 3]
list3 = [1, 2, 3+0.5]
list4 = [1+0.5, 2+0.5, 3]
list5 = [1, 2+0.5, 3+0.5]
list6 = [1+0.5, 2, 3+0.5]
list7 = [1+0.5, 2+0.5, 3+0.5]

list8 = [1+1, 2, 3]
list9 = [1,2+1,3]
list10 = [1,2,3+1]
list 11 = [1+1,2+1,3]
...
list = [1+0.5, 2+1, 3]
list = [1+0.5, 2, 3+1]
...
增加了问题的复杂性,我想做上述操作,但有一个限制:例如,新列表中所有元素的总和应该小于8

有什么好办法吗?可能递归地给出我的初始列表大约有30个元素,而我的第二个列表大约有5个元素


谢谢。

您可以对生成器使用递归,提供一个条件来检查累计和的运行值:

具有演示字符串表示的解决方案:

def pairs(a, b, _l, _c = []):
  if len(_c) == _l:
    yield _c
  else:
     if a:
       for i in b:
         yield from pairs(a[1:], b, _l, _c=_c+[f'{a[0]}+{i}'])
         yield from pairs(a[1:], b, _l, _c= _c+[a[0]])

print(list(pairs([1, 2, 3], [0.5, 1], 3)))
输出:

[['1+0.5', '2+0.5', '3+0.5'], ['1+0.5', '2+0.5', 3], ['1+0.5', '2+0.5', '3+1'], ['1+0.5', '2+0.5', 3], ['1+0.5', 2, '3+0.5'], ['1+0.5', 2, 3], ['1+0.5', 2, '3+1'], ['1+0.5', 2, 3], ['1+0.5', '2+1', '3+0.5'], ['1+0.5', '2+1', 3], ['1+0.5', '2+1', '3+1'], ['1+0.5', '2+1', 3], ['1+0.5', 2, '3+0.5'], ['1+0.5', 2, 3], ['1+0.5', 2, '3+1'], ['1+0.5', 2, 3], [1, '2+0.5', '3+0.5'], [1, '2+0.5', 3], [1, '2+0.5', '3+1'], [1, '2+0.5', 3], [1, 2, '3+0.5'], [1, 2, 3], [1, 2, '3+1'], [1, 2, 3], [1, '2+1', '3+0.5'], [1, '2+1', 3], [1, '2+1', '3+1'], [1, '2+1', 3], [1, 2, '3+0.5'], [1, 2, 3], [1, 2, '3+1'], [1, 2, 3], ['1+1', '2+0.5', '3+0.5'], ['1+1', '2+0.5', 3], ['1+1', '2+0.5', '3+1'], ['1+1', '2+0.5', 3], ['1+1', 2, '3+0.5'], ['1+1', 2, 3], ['1+1', 2, '3+1'], ['1+1', 2, 3], ['1+1', '2+1', '3+0.5'], ['1+1', '2+1', 3], ['1+1', '2+1', '3+1'], ['1+1', '2+1', 3], ['1+1', 2, '3+0.5'], ['1+1', 2, 3], ['1+1', 2, '3+1'], ['1+1', 2, 3], [1, '2+0.5', '3+0.5'], [1, '2+0.5', 3], [1, '2+0.5', '3+1'], [1, '2+0.5', 3], [1, 2, '3+0.5'], [1, 2, 3], [1, 2, '3+1'], [1, 2, 3], [1, '2+1', '3+0.5'], [1, '2+1', 3], [1, '2+1', '3+1'], [1, '2+1', 3], [1, 2, '3+0.5'], [1, 2, 3], [1, 2, '3+1'], [1, 2, 3]]
[[1.5, 2.5, 3.5], [1.5, 2.5, 3], [1.5, 2.5, 3], [1.5, 2, 3.5], [1.5, 2, 3], [1.5, 2, 4], [1.5, 2, 3], [1.5, 3, 3], [1.5, 3, 3], [1.5, 2, 3.5], [1.5, 2, 3], [1.5, 2, 4], [1.5, 2, 3], [1, 2.5, 3.5], [1, 2.5, 3], [1, 2.5, 4], [1, 2.5, 3], [1, 2, 3.5], [1, 2, 3], [1, 2, 4], [1, 2, 3], [1, 3, 3.5], [1, 3, 3], [1, 3, 3], [1, 2, 3.5], [1, 2, 3], [1, 2, 4], [1, 2, 3], [2, 2.5, 3], [2, 2.5, 3], [2, 2, 3.5], [2, 2, 3], [2, 2, 3], [2, 2, 3.5], [2, 2, 3], [2, 2, 3], [1, 2.5, 3.5], [1, 2.5, 3], [1, 2.5, 4], [1, 2.5, 3], [1, 2, 3.5], [1, 2, 3], [1, 2, 4], [1, 2, 3], [1, 3, 3.5], [1, 3, 3], [1, 3, 3], [1, 2, 3.5], [1, 2, 3], [1, 2, 4], [1, 2, 3]]
[[0, 1, 2], [0, 1, 3], [0, 1, 4], [0, 1, 3], [0, 2, 2], [0, 2, 3], [0, 2, 4], [0, 2, 3], [0, 3, 2], [0, 3, 3], [0, 3, 4], [0, 3, 3], [0, 2, 2], [0, 2, 3], [0, 2, 4], [0, 2, 3], [1, 1, 2], [1, 1, 3], [1, 1, 4], [1, 1, 3], [1, 2, 2], [1, 2, 3], [1, 2, 4], [1, 2, 3], [1, 3, 2], [1, 3, 3], [1, 3, 3], [1, 2, 2], [1, 2, 3], [1, 2, 4], [1, 2, 3], [2, 1, 2], [2, 1, 3], [2, 1, 4], [2, 1, 3], [2, 2, 2], [2, 2, 3], [2, 2, 3], [2, 3, 2], [2, 2, 2], [2, 2, 3], [2, 2, 3], [1, 1, 2], [1, 1, 3], [1, 1, 4], [1, 1, 3], [1, 2, 2], [1, 2, 3], [1, 2, 4], [1, 2, 3], [1, 3, 2], [1, 3, 3], [1, 3, 3], [1, 2, 2], [1, 2, 3], [1, 2, 4], [1, 2, 3]]
添加和修剪的解决方案:

def pairs(a, b, _l, _c = [], _sum=0):
  if len(_c) == _l:
    yield _c
  else:
    if a:
      for i in b:
        if a[0]+i+_sum < 8:
          yield from pairs(a[1:], b, _l, _c=_c+[a[0]+i], _sum=_sum+a[0]+i)
        if a[0]+_sum < 8:
          yield from pairs(a[1:], b, _l, _c= _c+[a[0]], _sum=_sum+a[0])

print(list(pairs([1, 2, 3], [0.5, 1], 3, _sum=0)))
编辑:指定下限:

def pairs(a, b, _l, _c = [], _sum=0):
  if len(_c) == _l:
    if _sum > 2:
      yield _c
  else:
    if a:
      for i in b:
        if a[0]+i+_sum < 8:
          yield from pairs(a[1:], b, _l, _c=_c+[a[0]+i], _sum=_sum+a[0]+i)
        if a[0]+_sum < 8:
          yield from pairs(a[1:], b, _l, _c= _c+[a[0]], _sum=_sum+a[0])

print(list(pairs([1, 2, 3], [-1, 1], 3, _sum=0)))

您可以对生成器使用递归,提供一个条件来检查累计和的运行值:

具有演示字符串表示的解决方案:

def pairs(a, b, _l, _c = []):
  if len(_c) == _l:
    yield _c
  else:
     if a:
       for i in b:
         yield from pairs(a[1:], b, _l, _c=_c+[f'{a[0]}+{i}'])
         yield from pairs(a[1:], b, _l, _c= _c+[a[0]])

print(list(pairs([1, 2, 3], [0.5, 1], 3)))
输出:

[['1+0.5', '2+0.5', '3+0.5'], ['1+0.5', '2+0.5', 3], ['1+0.5', '2+0.5', '3+1'], ['1+0.5', '2+0.5', 3], ['1+0.5', 2, '3+0.5'], ['1+0.5', 2, 3], ['1+0.5', 2, '3+1'], ['1+0.5', 2, 3], ['1+0.5', '2+1', '3+0.5'], ['1+0.5', '2+1', 3], ['1+0.5', '2+1', '3+1'], ['1+0.5', '2+1', 3], ['1+0.5', 2, '3+0.5'], ['1+0.5', 2, 3], ['1+0.5', 2, '3+1'], ['1+0.5', 2, 3], [1, '2+0.5', '3+0.5'], [1, '2+0.5', 3], [1, '2+0.5', '3+1'], [1, '2+0.5', 3], [1, 2, '3+0.5'], [1, 2, 3], [1, 2, '3+1'], [1, 2, 3], [1, '2+1', '3+0.5'], [1, '2+1', 3], [1, '2+1', '3+1'], [1, '2+1', 3], [1, 2, '3+0.5'], [1, 2, 3], [1, 2, '3+1'], [1, 2, 3], ['1+1', '2+0.5', '3+0.5'], ['1+1', '2+0.5', 3], ['1+1', '2+0.5', '3+1'], ['1+1', '2+0.5', 3], ['1+1', 2, '3+0.5'], ['1+1', 2, 3], ['1+1', 2, '3+1'], ['1+1', 2, 3], ['1+1', '2+1', '3+0.5'], ['1+1', '2+1', 3], ['1+1', '2+1', '3+1'], ['1+1', '2+1', 3], ['1+1', 2, '3+0.5'], ['1+1', 2, 3], ['1+1', 2, '3+1'], ['1+1', 2, 3], [1, '2+0.5', '3+0.5'], [1, '2+0.5', 3], [1, '2+0.5', '3+1'], [1, '2+0.5', 3], [1, 2, '3+0.5'], [1, 2, 3], [1, 2, '3+1'], [1, 2, 3], [1, '2+1', '3+0.5'], [1, '2+1', 3], [1, '2+1', '3+1'], [1, '2+1', 3], [1, 2, '3+0.5'], [1, 2, 3], [1, 2, '3+1'], [1, 2, 3]]
[[1.5, 2.5, 3.5], [1.5, 2.5, 3], [1.5, 2.5, 3], [1.5, 2, 3.5], [1.5, 2, 3], [1.5, 2, 4], [1.5, 2, 3], [1.5, 3, 3], [1.5, 3, 3], [1.5, 2, 3.5], [1.5, 2, 3], [1.5, 2, 4], [1.5, 2, 3], [1, 2.5, 3.5], [1, 2.5, 3], [1, 2.5, 4], [1, 2.5, 3], [1, 2, 3.5], [1, 2, 3], [1, 2, 4], [1, 2, 3], [1, 3, 3.5], [1, 3, 3], [1, 3, 3], [1, 2, 3.5], [1, 2, 3], [1, 2, 4], [1, 2, 3], [2, 2.5, 3], [2, 2.5, 3], [2, 2, 3.5], [2, 2, 3], [2, 2, 3], [2, 2, 3.5], [2, 2, 3], [2, 2, 3], [1, 2.5, 3.5], [1, 2.5, 3], [1, 2.5, 4], [1, 2.5, 3], [1, 2, 3.5], [1, 2, 3], [1, 2, 4], [1, 2, 3], [1, 3, 3.5], [1, 3, 3], [1, 3, 3], [1, 2, 3.5], [1, 2, 3], [1, 2, 4], [1, 2, 3]]
[[0, 1, 2], [0, 1, 3], [0, 1, 4], [0, 1, 3], [0, 2, 2], [0, 2, 3], [0, 2, 4], [0, 2, 3], [0, 3, 2], [0, 3, 3], [0, 3, 4], [0, 3, 3], [0, 2, 2], [0, 2, 3], [0, 2, 4], [0, 2, 3], [1, 1, 2], [1, 1, 3], [1, 1, 4], [1, 1, 3], [1, 2, 2], [1, 2, 3], [1, 2, 4], [1, 2, 3], [1, 3, 2], [1, 3, 3], [1, 3, 3], [1, 2, 2], [1, 2, 3], [1, 2, 4], [1, 2, 3], [2, 1, 2], [2, 1, 3], [2, 1, 4], [2, 1, 3], [2, 2, 2], [2, 2, 3], [2, 2, 3], [2, 3, 2], [2, 2, 2], [2, 2, 3], [2, 2, 3], [1, 1, 2], [1, 1, 3], [1, 1, 4], [1, 1, 3], [1, 2, 2], [1, 2, 3], [1, 2, 4], [1, 2, 3], [1, 3, 2], [1, 3, 3], [1, 3, 3], [1, 2, 2], [1, 2, 3], [1, 2, 4], [1, 2, 3]]
添加和修剪的解决方案:

def pairs(a, b, _l, _c = [], _sum=0):
  if len(_c) == _l:
    yield _c
  else:
    if a:
      for i in b:
        if a[0]+i+_sum < 8:
          yield from pairs(a[1:], b, _l, _c=_c+[a[0]+i], _sum=_sum+a[0]+i)
        if a[0]+_sum < 8:
          yield from pairs(a[1:], b, _l, _c= _c+[a[0]], _sum=_sum+a[0])

print(list(pairs([1, 2, 3], [0.5, 1], 3, _sum=0)))
编辑:指定下限:

def pairs(a, b, _l, _c = [], _sum=0):
  if len(_c) == _l:
    if _sum > 2:
      yield _c
  else:
    if a:
      for i in b:
        if a[0]+i+_sum < 8:
          yield from pairs(a[1:], b, _l, _c=_c+[a[0]+i], _sum=_sum+a[0]+i)
        if a[0]+_sum < 8:
          yield from pairs(a[1:], b, _l, _c= _c+[a[0]], _sum=_sum+a[0])

print(list(pairs([1, 2, 3], [-1, 1], 3, _sum=0)))

如果没有更严格的约束,你所描述的是不可能的(甚至可能在那时也是不可能的)

让我们只看一组
list
s。想象一下,您正在尝试将30个索引添加到15个索引中,所有五个可能的值都在发挥作用。这是515种(超过3000万)方法来填写15个选定的指数,30种选择15组指数来填写(超过1.55亿),这一共是473381103515620000(47.5亿)个列表。可能会少一点,因为您必须至少使用五个值中的每个值一次(否则您将使用较小的选定值集重新计算相同的
列表
),但这仍然是疯狂的。这只是针对15个指数,5个值的情况;其他的会稍微小一些,但大多数在人的一生中仍然不可能单独计算,更不用说总量计算了

您可以尝试通过预先计算大输入列表的总和,跳过保证超过最大累积值的任何值的组合,以及预先减少将使您超过上限的任何值的多重性来过滤它。但这气味很重;任何时候,当你考虑这种组合疯狂的程度时,你可能有更好的方法来完成你的任务(和/或你的任务是不可能的)

对于您的简单案例,您只需结合
itertools
工具即可:

from itertools import combinations, product

def make_lists(list1, list2, limit):
    maxvalues = limit - sum(list1)
    minlist2 = min(list2)
    for numindices in range(1, len(list1)+1):
        if minlist2 * numindices >= maxvalues:
            continue
        for indices in combinations(range(len(list1)), numindices):
            for values in product([x for x in list2 if x < maxvalues], repeat=numindices):
                if sum(values) >= maxvalues:
                    continue
                newlist = list1[:]
                for i, v in zip(indices, values):
                    newlist[i] += v
                yield newlist
来自itertools导入组合,产品
def make_列表(列表1、列表2、限制):
maxvalues=限制-总和(列表1)
minlist2=min(list2)
对于范围(1,len(列表1)+1)内的裸体:
如果minlist2*numindices>=最大值:
持续
对于组合索引(范围(len(list1)),numindices:
对于产品中的值([x代表列表2中的x,如果x=最大值:
持续
newlist=list1[:]
对于zip中的i、v(索引、值):
新列表[i]+=v
收益新列表

但对于任何有意义的输入长度来说,这都需要“宇宙热死亡”的时间。递归解决方案可以更有效地过滤无效输出,但除非限制真的很严格,否则在程序完成之前,您仍将死亡。

如果没有更严格的约束,您所描述的是不可能的(甚至可能是不可能的)

让我们只看一组
list
s。想象一下,您正在尝试将30个索引添加到15个索引中,所有五个可能的值都在发挥作用。这是515种(超过3000万)方法来填写15个选定的指数,30种选择15组指数来填写(超过1.55亿),这一共是473381103515620000(47.5亿)个列表。可能会少一点,因为您必须至少使用五个值中的每个值一次(否则您将使用较小的选定值集重新计算相同的
列表
),但这仍然是疯狂的。这只是针对15个指数,5个值的情况;其他的会稍微小一些,但大多数在人的一生中仍然不可能单独计算,更不用说总量计算了

您可以尝试通过预先计算大输入列表的总和,跳过保证超过最大累积值的任何值的组合,以及预先减少将使您超过上限的任何值的多重性来过滤它。但这气味很重;任何时候,当你考虑这种组合疯狂的程度时,你可能有更好的方法来完成你的任务(和/或你的任务是不可能的)

对于您的简单案例,您只需结合
itertools
工具即可:

from itertools import combinations, product

def make_lists(list1, list2, limit):
    maxvalues = limit - sum(list1)
    minlist2 = min(list2)
    for numindices in range(1, len(list1)+1):
        if minlist2 * numindices >= maxvalues:
            continue
        for indices in combinations(range(len(list1)), numindices):
            for values in product([x for x in list2 if x < maxvalues], repeat=numindices):
                if sum(values) >= maxvalues:
                    continue
                newlist = list1[:]
                for i, v in zip(indices, values):
                    newlist[i] += v
                yield newlist
来自itertools导入组合,产品
def make_列表(列表1、列表2、限制):
maxvalues=限制-总和(列表1)
minlist2=min(list2)
对于范围(1,len(列表1)+1)内的裸体:
如果minlist2*numindices>=最大值:
持续
对于组合索引(范围(len(list1)),numindices:
对于产品中的值([x代表列表2中的x,如果x=最大值:
持续
newlist=list1[:]
对于zip中的i、v(索引、值):
新列表[i]+=v
收益新列表

但对于任何有意义的输入长度来说,这都需要“宇宙热死亡”的时间。递归解决方案可以更有效地过滤无效的输出,但除非限制非常严格,否则在程序完成之前,您仍将死亡。

这是一场组合噩梦。你有5个选择