擅长:python、mysql、java
<p>对于<em>快速</em>、完全矢量化的方式(无循环),您可以使用常规的<code>np.cumsum()</code>,但在数组的副本上,您可以在每个组的开头减去上一个组的和:</p>
<pre><code>def group_cumsum(s):
# make a copy and ensure np.array (in case list was given)
s = np.array(s).copy()
idx = np.nonzero(np.diff(s))[0] # last of each group
off = np.diff(np.concatenate(([0], np.cumsum(s)[idx])))
s[idx + 1] -= off
return np.cumsum(s)
</code></pre>
<p>例如:</p>
<pre><code>print(group_cumsum([1, 1, 1, -1, -1, -1, -1]))
# [ 1 2 3 -1 -2 -3 -4]
print(group_cumsum([1]*3 + [-1]*2 + [1]*4 + [-1]*5))
# [ 1 2 3 -1 -2 1 2 3 4 -1 -2 -3 -4 -5]
</code></pre>
<p><strong>对于大型阵列,节省的时间非常可观</strong>:</p>
<ol>
<li>Python代码中没有循环,所有操作都是矢量化的,并且</li>
<li>在大小为<code>n</code>的数组中<code>k</code>组是<code>O(n + k)</code>(不同于<code>O(n * k)</code>的其他解决方案)</李>
</ol>
<p>试试这个:</p>
<pre><code>s = np.random.choice([1, -1], size=(int(1e6)))
%%timeit
group_cumsum(s)
19.1 ms ± 137 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)
</code></pre>