2

I'm new to javascript, I have array object, which has keys total,failure with there respective integer values. I want to add the total of all the array objects and also want to derive total percentage of failure out of total sum up value

With javascript reduce function, I'm able to add the total of all array objects, but not able to get percentage of failure to total sum up value. Please do suggest here with your valuable input

Here is my code below :

var data = [
{"total":728, "failure": 76}, 
{"total":708, "failure": 56}, 
{"total":435, "failure": 36}, 
{"total":324, "failure": 93},
{"total":649, "failure": 65}
]

var r = data.reduce((a, b) => ({total: a.total + b.total}));
console.log(r)

Here with reduce function, I"m able to add total and getting the count, now I need failure in percent to total count using reduce function. Please suggest

David
  • 25
  • 5

2 Answers2

2

If failure is a percentage, you need to take care how to accumulate such a figure. You should first convert such percentage to an absolute failure count, sum that up, and then convert back to a percentage:

var data = [
  {"total":728, "failure": 76}, 
  {"total":708, "failure": 56}, 
  {"total":435, "failure": 36}, 
  {"total":324, "failure": 93},
  {"total":649, "failure": 65}
];

const res = data.reduce((acc, b) => ({
    total: acc.total + b.total,
    failureCount: acc.failureCount  + Math.round(b.total * b.failure/100)
}), { total: 0, failureCount: 0 });

res.failure = Math.round(res.failureCount / res.total * 100);

console.log(res);

I assume the first Math.round is necessary, as it seem unreasonable that a failure count would not be an integer number. The final application of Math.round is a merely a choice. If you want a more accurate percentage, you can leave that one out.

trincot
  • 317,000
  • 35
  • 244
  • 286
1

Here's a pretty quick and succinct way using destructuring syntax:

const data = [{total:728,failure:76},{total:708,failure:56},{total:435,failure:36},{total:324,failure:93},{total:649,failure:65}];

const [total, failure] = data.reduce(
  ([total, failure], d) => [
    total + d.total,
    failure + d.failure
  ],
  [0, 0]
);

console.log(total, failure / total * 100)

If failure is already a percentage and not just a count, then you need to multiply each percentage with its respective total to get the failure count, then divide the aggregates in the return value of reduce() the same as above:

const data = [{total:728,failure:76},{total:708,failure:56},{total:435,failure:36},{total:324,failure:93},{total:649,failure:65}];

const [total, failure] = data.reduce(
  ([total, failure], d) => [
    total + d.total,
    failure + d.failure * d.total / 100
  ],
  [0, 0]
);

console.log(total, failure / total * 100)
Patrick Roberts
  • 49,224
  • 10
  • 102
  • 153
  • is 11.46% the expected result?... sounds quite low to me – briosheje Jul 01 '19 at 19:40
  • @briosheje I interpreted the question to be indicating `failure` as a _count_ rather than a percentage in the data array, which looking at the values appears to consistently be around 1/10th of the `total` count. – Patrick Roberts Jul 01 '19 at 19:41
  • I'm confused indeed, as it looks like values are already expressed in percentage, but it's not actually mentioned. If so, it's just enough to divide by `data.length`, if I'm not wrong, since there is no need to calculate any percentage whatsoever. – briosheje Jul 01 '19 at 19:44
  • @briosheje it is not enough to divide by `data.length`, as the percentages will have different weights in the sum since the `total` count is not the same for each. This is called a _weighted_ average for that reason. – Patrick Roberts Jul 01 '19 at 19:46