Sumurai8 - 4 years ago 216

Javascript Question

In this question I encountered the following simplified problem:

We start with an array of Objects with a value attribute. We want to calculate for each value what percentage of the sum of values it is, and add it to the structure as a property. To do this, we need to know the sum of values, but this sum is not calculated beforehand.

`//Original data structure`

[

{ "value" : 123456 },

{ "value" : 12146 }

]

//Becomes

[

{

"value" : 123456,

"perc" : 0.9104

},

{

"value" : 12146 ,

"perc" : 0.0896

}

]

An easy, and probably most readable, solution is to go through the data structure twice. First we calculate the sum, then we calculate the percentage and add it to the data structure.

`var i;`

var sum = 0;

for( i = 0; i < data.length; i++ ) {

sum += data[i].value;

}

for( i = 0; i < data.length; i++ ) {

data[i].perc = data[i].value / sum;

}

Can we instead just go through the data structure once, and somehow tell that the percentage expression should only be evaluated once the entire sum is known?

Recommended for you: Get network issues from **WhatsUp Gold**. **Not end users.**

Answer Source

The only way to make this with one less loop is to write out the whole sum statement made up of all possible items, for instance

```
var sum = (data[0] ? data[0].value : 0) +
(data[1] ? data[1].value : 0) +
(data[2] ? data[2].value : 0) +
...
(data[50] ? data[50].value : 0);
for( i = 0; i < data.length; i++ ) {
data[i].perc = data[i].value / sum;
}
```

You could use Array's reduce function but that is still a loop in the background, and a function call for each array element:

```
var sum = data.reduce(function(output,item){
return output+item.value;
},0);
for( i = 0; i < data.length; i++ ) {
data[i].perc = data[i].value / sum;
}
```

You could use the ES6 Promise, but there you are still adding a bunch of function calls

```
var data = [
{ "value" : 123456 },
{ "value" : 12146 }
]
var sum = 0;
var rej = null;
var res = null;
var def = new Promise(function(resolve,reject){
rej = reject;
res = resolve;
});
function perc(total){
this.perc = this.value/total;
}
for( i = 0; i < data.length; i++ ) {
def.then(perc.bind(data[i]));
sum+=data[i].value;
}
res(sum);
```

Addition statement

10,834,196

±0.44%

fastestReduce

3,552,539

±1.95%

67% slowerPromise

26,325

±8.14%

100% slowerFor loops

9,640,800

±0.45%

11% slower

Recommended from our users: **Dynamic Network Monitoring from WhatsUp Gold from IPSwitch**. ** Free Download**