user1735921 - 7 months ago 60
Javascript Question

# Javascript reduce function

Hello I have an array as follows:

``````[[1,1],[2,8],[3,12],[4,13],[5,23],[6,30],[7,41],[8,44],[9,50]]
``````

So lets say it is the format of
`[[x,y]]`

As you can see the above array, the first element inside inner arrays goes from
`1,2...6`
which is x, and the second element of inner arrays are
`1,8,12,13,23 and 30`
which is y.
This is a cumulative array of y and I want to convert it into non-cumulative but with a twist.

I want to convert y to non-cumulative array by getting the difference from the value of y at last 3rd value of x

Therefore I want the final result to be as follows:

``````[[1,1],[2,8],[3,0],[4,1],[5,11],[6,0],[7,11],[8,14],[9,0]]
``````

I have tried a fiddle here:
https://jsfiddle.net/gxytx6ka/1/

So far I have been able to get the difference between two array elements by some help of Dekel (stackoverflow guy) as you can see in the above fiddle:

``````\$(document).ready(function() {
var old_arr = [ [1, 1], [2, 8], [3, 12], [4, 13], [5, 23], [6, 30], [7, 41], [8, 44], [9, 50] ];
var new_arr = old_arr.reduce(function(a, b, c, d) {
if (a.length) {
a.push([d[c][0], d[c][1] - d[c - 1][1]])
} else {
a = [b]
}
return a;
}, []);

console.log(new_arr);
});``````

``<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>``

which outputs:

``````[[1,1],[2,7],[3,4],[4,1],[5,10],[6,7],[7,11],[8,3],[9,6]]
``````

but I want:

``````[[1,1],[2,8],[3,0],[4,1],[5,11],[6,0],[7,11],[8,14],[9,0]]
``````

which I am not able to get.

I tried using
`a%3==0`
in if condition, but not working...
Basically I want the final output in an efficient way.

With `reduce` you can do it like this (also using ES6 arrow function and spread operator):

``````var arr = [[1,1], [2,8], [3,12], [4,13], [5,23], [6,30], [7,41], [8,44], [9,50]];

var result = arr.reduce( ([arr, v], [x, y], i) =>
[[...arr,[x, i%3==2 ? 0 : y-v]], i%3==2 ? y : v], [[],0])[0];

console.log(result);``````

### Explanation

`reduce` is called with a double initial value (a pair):

``````[[],0]
``````

The first element is the array that will accumulate into the final result, and the second value is the current value to which subsequent `y` values will be offset.

These two values are captured by the argument `[arr, v]` which is a destructuring assignment (ES6). The `reduce` callback will always return a new pair like that, with extended `arr` and (potentially) updated `v`.

The callback function also takes the current `[x, y]` pair from the original array. Again this is a destructuring assignment, so you have direct access to `x` and `y` variables. The third argument `i` is the current, zero-based index in the original array.

As said, the callback returns a pair. The first element in that pair is constructed as follows:

``````[...arr, [x, i%3==2 ? 0 : y-v]]
``````

The `...arr` notation spreads the previously collected result elements as a list, and one pair is added to that list: `[x, i%3==2 ? 0 : y-v]`. The `x` is just reproduced from the original `[x, y]`, but the `y` follows the requested logic with the ternary operator: if we are at an index that has a remainder of 2 when divided by 3, then the `y` value should be 0. Otherwise, it should be offset against the previously set value `v`.

The second element in the pair, must be the new value for `v`:

``````i%3==2 ? y : v
``````

Again, according to the requested logic, `v` remains unchanged when the remainder is not 2, but otherwise it is set to the current value of `y`.

So `reduce` will thus accumulate/update these two values in each iteration, and finally return a pair, of which only the first has our interest, which is why there is `[0]` at the end.

### Notes

As you seemed to be looking for a `reduce` implementation, that is what I went with, but whenever your output array as just as many elements as your input array (like is the case here) you can also consider to use `map` as a good alternative (See answer that NinaScholz posted).

If you are open for a less functional programming way, you can also choose to use a `for` loop and maybe gain a bit of performance.

Source (Stackoverflow)