Python循环或任何迭代以查找所有组合,从而满足条件

Python循环或任何迭代以查找所有组合,从而满足条件,python,loops,combinations,Python,Loops,Combinations,我想找到所有可能的n个数字的组合,这样在Python中的和等于100 两个数字的样本: x=[] for i, j in itertools.product(range(0,101), range(0,101)): if i+j==100: x.append([i,j]) 任何替代和聪明的方法都可以通过可变数量的迭代变量实现这一点,并以以下形式获得结果: n=5: 这是对您的算法的一个微不足道的概括/部分优化 编辑:使用重复比此解决方案更可取 import itertoo

我想找到所有可能的n个数字的组合,这样在Python中的和等于100

两个数字的样本:

x=[]
for i, j in itertools.product(range(0,101), range(0,101)):
    if i+j==100:
       x.append([i,j])
任何替代和聪明的方法都可以通过可变数量的迭代变量实现这一点,并以以下形式获得结果: n=5:


这是对您的算法的一个微不足道的概括/部分优化

编辑:使用
重复
比此解决方案更可取

import itertools

n = 3
x = []

x = [list(i) for i in itertools.product(*(range(0,101) \
             for _ in range(n))) if sum(i) == 100]

itertools.product
接受一个
repeat
参数,您可以使用该参数来
repeat
范围(1101)迭代器
repeat
次数。这样,您就不需要多次指定迭代器或生成所需数量的参数。例如,对于5次:

[i for i in itertools.product(range(1, 101), repeat=5) if sum(i) == 100]

纯Python解决方案(即没有
itertools.product

这里的主要困难是在函数内部为循环执行数量可变的
。我们可以很容易地解决这个问题的方法是使用递归,它涉及到函数本身的调用

如果我们使用递归,那么在函数的任何实例中,实际上只有一个
for循环
。因此,要将此应用于手头的问题,我们希望我们的函数采用两个参数:我们试图求和的数字的目标,以及可用的正整数的数量

然后,每个函数将以二维
列表的形式返回(给定
目标
n
数字)将构成该目标的所有组合

我们必须考虑的唯一的特殊情况是递归树的“叶节点”(我们有某个目标的情况,但是<代码> n== 1 ,所以我们只有一个数字来做目标)。这很容易处理,我们只需要记住,我们应该始终返回构成目标的所有组合,因此在这种情况下,只有一个“组合”,即

目标

然后(如果
n>1
),其余的都是不言自明的,我们只需循环遍历小于
target
的每个数字,并添加到组合(
cs
)的
列表中,以获得再次调用函数的结果

但是,在我们将这些组合连接到
列表
之前,我们需要使用
理解
i
(下一个数字)添加到每个组合的开头

就这样!希望您能看到上面的代码如何转化为以下代码:

def combos(target, n):
    if n == 1:
        return [[target]]
    cs = []
    for i in range(0, target+1):
        cs += [[i]+c for c in combos(target-i, n-1)]
    return cs

一项测试(使用
target
作为
10
n
作为
3
以使其更清晰)表明它是有效的:

>>> combos(10, 3)
[[0, 0, 10], [0, 1, 9], [0, 2, 8], [0, 3, 7], [0, 4, 6], [0, 5, 5], [0, 6, 4], [0, 7, 3], [0, 8, 2], [0, 9, 1], [0, 10, 0], [1, 0, 9], [1, 1, 8], [1, 2, 7], [1, 3, 6], [1, 4, 5], [1, 5, 4], [1, 6, 3], [1, 7, 2], [1, 8, 1], [1, 9, 0], [2, 0, 8], [2, 1, 7], [2, 2, 6], [2, 3, 5], [2, 4, 4], [2, 5, 3], [2, 6, 2], [2, 7, 1], [2, 8, 0], [3, 0, 7], [3, 1, 6], [3, 2, 5], [3, 3, 4], [3, 4, 3], [3, 5, 2], [3, 6, 1], [3, 7, 0], [4, 0, 6], [4, 1, 5], [4, 2, 4], [4, 3, 3], [4, 4, 2], [4, 5, 1], [4, 6, 0], [5, 0, 5], [5, 1, 4], [5, 2, 3], [5, 3, 2], [5, 4, 1], [5, 5, 0], [6, 0, 4], [6, 1, 3], [6, 2, 2], [6, 3, 1], [6, 4, 0], [7, 0, 3], [7, 1, 2], [7, 2, 1], [7, 3, 0], [8, 0, 2], [8, 1, 1], [8, 2, 0], [9, 0, 1], [9, 1, 0], [10, 0, 0]]

提高性能

如果我们试图用<代码> 4 < /代码>数字来编写<代码> 10 <代码>。在某一点上,函数将在say

1
3
之后调用,目标为
6
。正如我们已经解释过的,该算法将使用
2
数字返回组合,以生成
6
。但是,如果我们现在考虑另一个情况,当函数被要求给出“<代码> 6”/代码>(与以前相同)的组合时,调用为“代码< 2”/代码>和<代码> 2 < /代码>。请注意,即使我们得到了正确的答案(通过递归和
for循环
),我们仍将返回与以前相同的组合—当我们使用
1
3
调用时。此外,这种情况极为常见:函数将在不同的情况下调用,但会被要求给出以前在不同时间计算过的相同组合

这让位于一种称为的伟大的优化技术,它本质上只是意味着在返回之前将函数的结果作为
键:值
对存储在字典(
mem
)中

然后,我们只需在每次函数调用开始时检查以前是否使用相同的参数调用过(通过查看键是否在字典中),如果是,则可以返回上次得到的结果

这大大加快了算法的速度

mem = {}
def combos(target, n):
    k = (target, n)
    if k in mem:
        return mem[k]
    if n == 1:
        return [[target]]
    cs = []
    for i in range(0, target+1):
        cs += [[i]+c for c in combos(target-i, n-1)]
    mem[k] = cs
    return cs

你是在寻找提高性能的方法,还是仅仅是替代方法?@jp_data_analysis yeap我在寻找快速生成这些数据并将其存储在txt文件中,每当我需要将它们作为计算索引时,我都能将其提取出来。如果有任何帮助,变量的数量可能会增加到几百个,总计大约10000个。该算法非常纯净,需要很长时间才能完成大量变量的运行。还有更好的选择吗?但你的演讲在这里很有用。大的是大的吗?我认为您低估了一个包含
5个
元素的列表的长度!我认为没有比这更好的了,对不起:/100个变量加起来是10000?我试了50个变量,花了很长时间编译,但还没有完成:/这太荒谬了!!!如果没有优化(itertools
方法),您将接近
100
itertations:这是一个巨大的数量-
~10^157
相比之下,在可观测的宇宙中估计有
10^80
个原子!任何计算机都不可能做你想做的事!是的,完全同意。因此,我想知道是否有任何优化,使这些计算时间易于管理
mem = {}
def combos(target, n):
    k = (target, n)
    if k in mem:
        return mem[k]
    if n == 1:
        return [[target]]
    cs = []
    for i in range(0, target+1):
        cs += [[i]+c for c in combos(target-i, n-1)]
    mem[k] = cs
    return cs