1

I have an array that looks like this:

Arr=[{"cause" : 1 , "solution" : "change"}, 
     {"cause" : 1 , "solution" : "rechange"}, 
     {"cause" : 2 , "solution" : "alter settings"}, 
     {"cause" : 1 , "solution" : "change"}, 
     {"cause" : 3 , "solution" : "change"},
     {"cause" : 4 , "solution" : "change"}, 
     {"cause" : 5 , "solution" : "reload"}];

I am trying to get calculate the occurrence of the solution based on the cause and store it in an array in percentages. For example, the occurrence of cause 1 and solution change is 2/3 so it will be 66.66% by multiplying it with 100. And here is my progress so far:

var ctr = [];
var percentageArr = [];

for (var a=0;a< Arr.length;a++){
    for (var b=0;b< Arr.length;b++){
       if (Arr [b]. cause == Arr [a]. cause){
          ctr++;
       }   
     }     
   ctr=ctr/( Arr.length)*100;
   ctr=ctr.toFixed(2);
   percentageArr.push(ctr);
   ctr=0;
}

Now with this output, I can get the percentage of the causes. But i am trying to get the percentage of the solutions based on the causes. I am currently thinking of adding another nested loop to check for the solution but am open to any suggestions

Sriram
  • 433
  • 4
  • 20

1 Answers1

2

You can use Array.prototype.reduce to group items by cause and counnt individual solutions for a cause.

Then you can update each solution by calculating the percentage by dividing solution count with the total counts for the cause

var arr = [{
    'cause': 1,
    'solution': 'change'
  },
  {
    'cause': 1,
    'solution': 'rechange'
  },
  {
    'cause': 2,
    'solution': 'alter settings'
  },
  {
    'cause': 1,
    'solution': 'change'
  },
  {
    'cause': 3,
    'solution': 'change'
  },
  {
    'cause': 4,
    'solution': 'change'
  },
  {
    'cause': 5,
    'solution': 'reload'
  }
];

var res = arr.reduce((acc, item, i) => {
  if (!acc[item.cause]) {
    acc[item.cause] = {
      [item.solution]: 1,
    }
  } else {
    acc[item.cause] = {
      ...acc[item.cause],
      [item.solution]: (acc[item.cause][item.solution] || 0) + 1
    }
  }
  return acc;
}, {});

for (let i in res) {
  const length = Object.values(res[i]).reduce((acc, i) => acc + i, 0);
  res[i] = Object.assign(...Object.entries(res[i]).map(([solution, number]) => ({
    [solution]: ((number / length) * 100).toFixed(2)
  })))
}

console.log(res);

Witth ES5 you can do it like

var arr = [
  {
    cause: 1,
    solution: 'change',
  },
  {
    cause: 1,
    solution: 'rechange',
  },
  {
    cause: 2,
    solution: 'alter settings',
  },
  {
    cause: 1,
    solution: 'change',
  },
  {
    cause: 3,
    solution: 'change',
  },
  {
    cause: 4,
    solution: 'change',
  },
  {
    cause: 5,
    solution: 'reload',
  },
];

var res = arr.reduce(function (acc, item, i) {
  if (!acc[item.cause]) {
    acc[item.cause] = {
      [item.solution]: 1,
    };
  } else {
    acc[item.cause] = Object.assign(
        acc[item.cause],
        {
          [item.solution]: acc[item.cause][item.solution]? acc[item.cause][item.solution] + 1: 1
        }
      );
  }
  return acc;
}, {});

for (let i in res) {
  const length = Object.values(res[i]).reduce(function (acc, i) {
    return acc + i;
  }, 0);
  for (let j in res[i]) {
    res[i][j] = ((res[i][j] / length) * 100).toFixed(2);
  }
}

console.log(res);
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • I got an error: Exception(NotImplementedError('Shorthand and Computed properties not implemented!')) – Sriram Apr 05 '21 at 15:33