OracleOfNJ - 9 months ago 37

Javascript Question

Is there a JavaScript equivalent to Clojure's "reductions" function or Python's

`itertools.accumulate`

`[x_0, x_1, x_2 ... x_n-1]`

`f(prev, next)`

`n`

`[x_0, f(x_0, x_1), f(f(x_0, x_1), x_2)... f(f(f(...)), x_n)]`

I'm simulating the desired behavior below:

`function accumsum(prev, next) {`

last = prev[prev.length - 1] || 0;

prev.push(last + next);

return prev;

}

var x = [1, 1, 1, 1];

var y = x.reduce(accumsum, []);

var z = y.reduce(accumsum, []);

console.log(x);

console.log(y);

console.log(z);

which displays:

`[ 1, 1, 1, 1 ]`

[ 1, 2, 3, 4 ]

[ 1, 3, 6, 10 ]

But I'm wondering if there is a way to write something simpler like

`[1, 1, 1, 1].reductions(function(prev, next) {return prev + next;});`

If not, is there a more idiomatic way to do this in JavaScript than what I wrote?

Answer Source

```
var a = [1, 1, 1, 1];
var c = 0;
a.map(function(x) { return c += x; })
// => [1, 2, 3, 4]
a.reduce(function(c, a) {
c.push(c[c.length - 1] + a);
return c;
}, [0]).slice(1);
// => [1, 2, 3, 4]
```

I'd use the first one, personally.

EDIT:

Is there a way of doing your first suggestion that doesn't require me to have a random global variable (c in this case) floating around? If I forgot to re-initialize c back to 0, the second time I wrote a.map(...) it would give the wrong answer.

Sure - you can encapsulate it.

```
function cumulativeReduce(fn, start, array) {
var c = start;
return array.map(function(x) {
return (c = fn(c, x));
});
}
cumulativeReduce(function(c, a) { return c + a; }, 0, [1, 1, 1, 1]);
// => [1, 2, 3, 4]
c
// => ReferenceError - no dangling global variables
```