从numpy数组中提取组合以求和到所需的输出

时间:2018-12-23 01:29:21

标签: 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]]

我可以想象使用itertools.combinations的方法,尽管我想避免这种情况,因为我要使用的数据集已经有大约30,000个成员。考虑每种组合长度时,它的运行速度不够快。

有更快的方法吗?

编辑:有关其他信息,我没有必要使用30,000个成员的每种组合。例如,我将整数总计为〜1000,因此我需要<1000个成分-在我的情况下,列表成分的结尾数可能由100-400个成分组成。

2 个答案:

答案 0 :(得分:2)

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

例如,使用0和10之间的10k个随机整数,我发现243905016604941663446994个子集的总和为10-这是一个24位数字。如果您可以每纳秒列出一个组合,则将花费700万年。总计为1000的30k个随机整数数组的数字应该大得多。

代码段,用于计算总计为数字的组合。

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

答案 1 :(得分:0)

如果您介意itertools.combinations,可以使用:

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

输出:

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

如果要订购,请排序:

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

输出:

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

您说itertools.combinations会很慢,但是除了itertools.combinations之外,实际上没有其他有效的方法。