假设我有一个NumPy数组:
x = np.array([3, 9, 2, 1, 5, 4, 7, 7, 8, 6])
如果我对这个数组求和,得到52
。我需要的是一种方法,从左到右将它分成大约n
个块,其中n
由用户选择。本质上,分裂是以贪婪的方式发生的。因此,对于一些块n
,第一个n - 1
块的总和必须至少达到52/n
,并且它们必须是从左到右的连续索引
因此,如果n = 2
,那么第一个块将由前7个元素组成:
chunk[0] = x[:7] # [3, 9, 2, 1, 5, 4, 7], sum = 31
chunk[1] = x[7:] # [7, 8, 6], sum = 21
请注意,第一个区块不会只包含前6个元素,因为总和将是小于52/2 = 26
的24
。另外,请注意,只要满足求和条件,每个块中的元素数量就可以改变。最后,最后一个块不接近52/2 = 26
是很好的,因为其他块可能需要更多的时间
但是,我需要的输出是一个两列数组,第一列中包含开始索引,第二列中包含(独占)停止索引:
[[0, 7],
[7, 10]]
如果n = 4
,那么前3个块需要至少加起来52/4 = 13
,如下所示:
chunk[0] = x[:3] # [3, 9, 2], sum = 14
chunk[1] = x[3:7] # [1, 5, 4], sum = 17
chunk[2] = x[7:9] # [7, 8], sum = 15
chunk[3] = x[9:] # [6], sum = 6
我需要的输出是:
[[0, 3],
[3, 7],
[7, 9],
[9, 10]
因此,使用for循环的一种简单方法可能是:
ranges = np.zeros((n_chunks, 2), np.int64)
ranges_idx = 0
range_start_idx = start
sum = 0
for i in range(x.shape[0]):
sum += x[i]
if sum > x.sum() / n_chunks:
ranges[ranges_idx, 0] = range_start_idx
ranges[ranges_idx, 1] = min(
i + 1, x.shape[0]
) # Exclusive stop index
# Reset and Update
range_start_idx = i + 1
ranges_idx += 1
sum = 0
# Handle final range outside of for loop
ranges[ranges_idx, 0] = range_start_idx
ranges[ranges_idx, 1] = x.shape[0]
if ranges_idx < n_chunks - 1:
left[ranges_idx:] = x.shape[0]
return ranges
我正在寻找一个更好的矢量化解决方案
以下是一个不会迭代所有元素的解决方案:
对于这两个测试用例,它会产生您期望的结果。嗯
我从一个similar question that was answered中找到灵感:
更新
为了涵盖病理病例,我们需要更精确一点,并采取如下措施:
相关问题 更多 >
编程相关推荐