Python 从一个numpy数组中提取总和为所需输出的组合

Python 从一个numpy数组中提取总和为所需输出的组合,python,numpy,Python,Numpy,我想返回一个数组或其索引,其中包含numpy数组中哪些成员组合与特定数字相加 例如,如果我使用此数组并希望找到其成员的所有组合,其总和为7: import numpy as np example = np.arange(4) + 1 example >>> array([1, 2, 3, 4]) 它将返回: somefunction >>> [[1,2,4], [3,4]] 或索引: >>> [[0,1,2], [2,3]] 我可以

我想返回一个数组或其索引,其中包含numpy数组中哪些成员组合与特定数字相加

例如,如果我使用此数组并希望找到其成员的所有组合,其总和为7:

import numpy as np

example = np.arange(4) + 1

example
>>> array([1, 2, 3, 4])
它将返回:

somefunction
>>> [[1,2,4], [3,4]]
或索引:

>>> [[0,1,2], [2,3]]
我可以想象一种使用
itertools.combines
的方法,尽管我希望避免这种情况,因为我试图使用它的数据集已经有大约30000个成员。当考虑到组合的每个长度时,它的运行速度不够快

有没有更快的方法


编辑:对于其他信息,我并没有必要使用30000个成员的每个组合。例如,我将整数相加到~1000,因此我需要<1000个成分-在我的例子中,列表成分的结束数可能由100-400个成分组成。

如果您介意的话,可以使用
itertools.compositions

print([x for i in range(1,4) for x in itertools.combinations(example,i) if sum(x)==7])
输出:

[(3, 4), (1, 2, 4)]
[(1, 2, 4), (3, 4)]
如果您需要所需的顺序,请对其进行排序:

print(sorted([x for i in range(1,4) for x in itertools.combinations(example,i) if sum(x)==7]))
输出:

[(3, 4), (1, 2, 4)]
[(1, 2, 4), (3, 4)]

正如你所说的,
itertools.compositions
会很慢,但是除了
itertools.compositions
tho.

扩展注释而不是答案之外,没有其他有效的方法。根据数据的结构,列出具有给定总和的所有元素组合可能是不可行的。然而,有一种有效的方法来计算组合的数量。然后,您可以决定是否要尝试列出每一个

例如,对于0到10之间的10k随机整数,我发现
243905016604941663446994
的子集总和为10,这是一个24位数字。如果你能每纳秒列出一个组合,那就需要700多万年。一个30k随机整数的数组求和到
1000
的数目应该大得多

用于计算组合总和的代码段

import numpy as np
import sys

example = np.arange(4) + 1
example_target = 7

# assuming all elemenst of arr are positive integers
def count_combs(arr, sum_):
    arr = np.sort(arr)

    sys.setrecursionlimit(100_000)
    state_dict = {}

    def state(i, j):
        if (i, j) in state_dict:
            return state_dict[(i, j)]
        elif j < 0:
            res = 0
        elif j == 0:
            res = 1
        elif i == 0:
            res = 1 if j == arr[i] else 0
        else:
            res = state(i - 1, j - arr[i]) + state(i - 1, j)
        state_dict[(i, j)] = res
        return res

    return state(arr.shape[0] - 1, sum_)


# print(count_combs(example, example_target))
# prints 2

test_big = np.random.randint(0, 10, size=10000)
test_target = 10


def test():
    print(count_combs(test_big, test_target))


if __name__ == "__main__":
    test()
    # e.g. 258364297793668558120414
将numpy导入为np
导入系统
示例=np.arange(4)+1
示例_目标=7
#假设arr的所有元素都是正整数
def计数梳(arr、sum):
arr=np.排序(arr)
系统设置递归限制(100_000)
state_dict={}
def状态(i,j):
如果(i,j)处于状态:
返回状态[i,j]
elif j<0:
res=0
elif j==0:
res=1
elif i==0:
如果j==arr[i]否则为0,则res=1
其他:
res=状态(i-1,j-arr[i])+状态(i-1,j)
国家法令[(i,j)]=res
返回res
返回状态(arr.shape[0]-1,和)
#打印(计数梳(示例,示例目标))
#印刷品2
test_big=np.random.randint(0,10,size=10000)
测试目标=10
def test():
打印(计数梳(测试大,测试目标))
如果名称=“\uuuuu main\uuuuuuuu”:
测试()
#例如25836429793668558120414

你能对数组进行排序吗?听起来像是DP换硬币的问题。编辑:实际上是的,你可以对数组进行排序,woopsyAlso,根据数组的内容,组合的数量可能非常大。例如,如果您有一个30k个1的数组,则有~
1.6e+38
子集的总和为
10
。在尝试列出所有组合之前,您可以有效地计算给定和的组合数。@training_whitespace我刚刚查找了这个问题。这很简洁,但是在列出组合之前知道组合的数量有好处吗?OP提到他的原始数组有30k个元素。这将尝试检查每个子集,可能需要一段时间:)说明这在问题中不是最优的。@拖尾_空格好吧,这是唯一有效的方法tho:-),递归会更糟,lol:D@Estif和我对尾随空格所说的一样:这是唯一有效的一个tho:-),递归会更糟,大声笑:D@U9-向前看,我敢肯定,你可以得到一个渐进加速与动态规划;尽管如此,这仍然可能是不切实际的。这非常有帮助。我不相信这个问题有什么好的答案,谢谢你的洞察力!