You have an array of arrays, but each constituent array is independent from the next so let's tackle them individually. Let's talk about [1, 1, 1, -1]
.
Your use of the phrase "partial sum" is very informative. The full sum could be implemented using reduce
:
[1, 1, 1, -1].reduce((x, y) => x + y);
// 2
But you want an array of partial sums. That's very similar to this usage of reduce
, but instead of retaining only the last computed result, we retain every intermediate value too. In other languages, this is called scan
(cf. F#, Haskell).
A javascript implementation of a generic scan
would probably look a lot like reduce
. In fact, you can implement it with reduce
, with just a little extra work:
function scan(array, callback) {
const results = [array[0]];
// reduce does all the heavy lifting for us, but we define a wrapper to pass to it.
array.reduce((...args) => {
// The wrapper forwards all those arguments to the callback, but captures the result...
const result = callback(...args);
// ...storing that intermediate result in our results array...
results.push(result);
// ...then passes it back to reduce to continue what it was doing.
return result;
});
return results;
}
// scan([1, 1, 1, -1], (x, y) => x + y) -> [1, 2, 3, 2]
A more robust implementation would hew closer to the standard library's reduce
, especially around initial values:
function scan(array, callback, initialValue) {
const results = [];
const reducer = (...args) => {
const result = callback(...args);
results.push(result);
return result;
};
if (arguments.length === 2) {
results.push(array[0]);
array.reduce(reducer);
} else {
results.push(initialValue);
array.reduce(reducer, initialValue);
}
return results;
}
Bringing it back together, if you'd like to do this for your arrays of arrays, it would just be a map
over scan
:
[[1, 1, 1, -1], [1, -1, -1], [1, 1]].map(a => scan(a, (x, y) => x + y));
// [[1, 2, 3, 2], [1, 0, -1], [1, 2]]
No copying necessary or side effects to watch out for, and you get a handy higher-order function out of it to boot!