肥皂起泡泡
这是一种方法 -def sum_by_signs(a): m1 = a<0 m2 = a>0 m0 = a==0 # or ~m1 & ~m2 p = np.flatnonzero(m0[:-1] | np.diff(m1) | np.diff(m2))+1 return np.add.reduceat(a, np.r_[0,p])或者将该np.r_[0部分带入布尔构造部分 -def sum_by_signs_v2(a): m1 = a<0 m2 = a>0 m0 = a==0 # or ~m1 & ~m2 p = np.flatnonzero(np.r_[True, m0[:-1] | np.diff(m1) | np.diff(m2)]) return np.add.reduceat(a, p)解释我们的想法是根据符号变化或当我们遇到一系列 0 时将数组拆分为“岛”,在这种情况下,我们希望将每个元素拆分为单独的元素。通过拆分,可以将其视为列表的列表,如果这样更容易理解的话。现在,游戏是我们如何获得这些分裂。我们需要表示这些岛屿的开始、停止索引的索引。如前所述,存在三种情况,符号从 变为+或-相反,或者 0 序列。因此,布尔掩码的结构用于为这些索引提供一次性切片,以检测从+到 的符号变化-,反之亦然np.diff(m1) | np.diff(m2)。最后一个m0[:-1]是针对 的序列0s。然后将这些指数输入np.add.reduceat以获得间隔求和。样本运行 -In [208]: aOut[208]: array([ 0, 0, 0, -1, -1, 0, 1, 2, 1, 1, 0, -1, 0, 1, 1, -1, -2])In [209]: sum_by_signs(a)Out[209]: array([ 0, 0, 0, -2, 0, 5, 0, -1, 0, 2, -3])In [211]: aOut[211]: array([ 1, 2, 0, -1, -1, 0, 1, 2, 1, 1, 0, -1, 0, 1, 1, -1, -2])In [212]: sum_by_signs(a)Out[212]: array([ 3, 0, -2, 0, 5, 0, -1, 0, 2, -3])In [214]: aOut[214]: array([ 1, 2, 0, -1, -1, 0, 1, 2, 1, 1, 0, -1, 0, 1, 1, -1, -2, 0])In [215]: sum_by_signs(a)Out[215]: array([ 3, 0, -2, 0, 5, 0, -1, 0, 2, -3, 0])
函数式编程
这解决了问题,但肯定有更聪明的方法来做到这一点array = [0, 0, 0, -1, -1, 0, 1, 2, 1, 1, 0, -1, 0, 1, 1, -1, -2]switch = 0while switch == 0: for i in range(len(array)): try: array[i+1] if array[i] > 0 and array[i+1] > 0: array[i] += array[i + 1] array.pop(i + 1) break elif array[i] < 0 and array[i+1] < 0: array[i] += array[i + 1] array.pop(i + 1) break except: switch = 1 break最后,数组的值为 [0, 0, 0, -2, 0, 5, 0, -1, 0, 2, -3]