user1735921 - 1 year ago 101

Javascript Question

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`

`1,8,12,13,23 and 30`

This is a cumulative array of

I want to convert

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`

Basically I want the final output in an efficient way.

Answer Source

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);
```

`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.

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.