Sum all the adjacent values in an array, with some conditions
The current accepted answer will get terribly slow for larger lists.
The following s/b useful for such cases.
fn=With[{s = Split[#, # != 0 &]},
Flatten[Total[s, {2}]*(UnitVector[Length@#, 1] & /@ s)]] &;
A speed comparison:
If speed is important, the following should be much faster than the alternatives:
agglomerate[e_] := Module[
{
b = ListCorrelate[{2,-1}, Unitize[e], {-1,1}, 0],
a = Accumulate[e],
res = ConstantArray[0, Length@e],
i = Range[Length[e]]
},
res[[Pick[i, Most@b, -1]]] = ListCorrelate[{-1,1}, a[[Pick[i, Rest@b, 2]]], -1, 0];
res
]
Your example:
agglomerate[{0,0,0,10,12,5,0,1,2,0}]
{0, 0, 0, 27, 0, 0, 0, 3, 0, 0}
Comparison with @kglr's solution:
data = RandomInteger[1, 10^6] RandomInteger[10^5, 10^6];
r1 = agglomerate[data]; //AbsoluteTiming
r2 = f2[data]; //AbsoluteTiming
r1 === r2
{0.106844, Null}
{1.79474, Null}
True
l = {0,0,0,10,12,5,0,1,2,0};
SequenceReplace[l, {x__ /; FreeQ[{x}, 0]} :>
Sequence @@ (Flatten@{Total[{x}], Table[0, Length[{x}] - 1]})]
(* {0, 0, 0, 27, 0, 0, 0, 3, 0, 0} *)