Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Reduce an arry of objects to an object with key value pairs with addition & comparision

I have an array of objects like this

const inputArray = [
  { name: "sam", date: "1 / 1 / 23", confirmed: "yes", spent: 0 },
  { name: "sam", date: "1 / 2 / 23", confirmed: "yes", spent: 4 },
  { name: "sam", date: "1 / 3 / 23", confirmed: "yes", spent: 4 },
  { name: "sam", date: "1 / 4 / 23", confirmed: "no", spent: 4 },
  { name: "bill", date: "1 / 5 / 23", confirmed: "yes", spent: 4 },
  { name: "bill", date: "1 / 6 / 23", confirmed: "yes", spent: 4 },
  { name: "bill", date: "1 / 5 / 23", confirmed: "yes", spent: 0 },
  { name: "annie", date: "1 / 6 / 23", confirmed: "yes", spent: 0 },
  { name: "annie", date: "1 / 6 / 23", confirmed: "no", spent: 2 },
  { name: "annie", date: "1 / 6 / 23", confirmed: "no", spent: 2 },
];

I want an output object like this

  • value of key spent is just an addition of all spent for a name
  • value of key confirmedAndNotSpent is just the addition of all confirmed as ‘yes’ but spent as 0 for a name
  • value of key notConfirmedAndSpent is just an addition of all confirmed as ‘no’ for a name
const outputObj = {
  sam: { spent: 12, confirmedAndNotSpent: 1, notConfirmedAndSpent: 1 },
  bill: { spent: 8, confirmedAndNotSpent: 1, notConfirmedAndSpent: 0 },
  bill: { spent: 4, confirmedAndNotSpent: 1, notConfirmedAndSpent: 2 },
};

How do I achieve this.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

I tired this first

let try1 = inputArray.reduce((accumulator, current) => {
  if (!accumulator[current.name]) accumulator[current.name] = 0;
  accumulator[current.name] += +current.spent;
  return accumulator;
}, {});

This gives the the output like so { sam: 12, bill: 8, annie: 4 }.

However, I am unable to convert even this into an object with the code below.

let try2 = inputArray.reduce((accumulator, current) => {
  if (!accumulator[current.name]) accumulator[current.name] = {};
  accumulator[current.name][current.spent] += +current.spent;
  return accumulator;
}, {})

The above code gives the out put below

{
  sam: { '0': NaN, '4': NaN },
  bill: { '0': NaN, '4': NaN },
  annie: { '0': NaN, '2': NaN }
}

Can anyone help to get the output I want? Thanks.

>Solution :

Two issues with your code:

  1. You made a typo. Where you declare try2, this line:
accumulator[current.name][current.spent] += +current.spent;

should be:

accumulator[current.name].spent += +current.spent;
  1. In JavaScript, undefined + 0 (or any number) is equal to NaN. To solve this. You have to first initialize your spent property to 0:
  if (!accumulator[current.name]) accumulator[current.name] = { spent: 0 }

For the other variables, these can all be accomplished in a similar manner, just with the necessary conditional checks.

const inputArray = [
  { name: "sam", date: "1 / 1 / 23", confirmed: "yes", spent: 0 },
  { name: "sam", date: "1 / 2 / 23", confirmed: "yes", spent: 4 },
  { name: "sam", date: "1 / 3 / 23", confirmed: "yes", spent: 4 },
  { name: "sam", date: "1 / 4 / 23", confirmed: "no", spent: 4 },
  { name: "bill", date: "1 / 5 / 23", confirmed: "yes", spent: 4 },
  { name: "bill", date: "1 / 6 / 23", confirmed: "yes", spent: 4 },
  { name: "bill", date: "1 / 5 / 23", confirmed: "yes", spent: 0 },
  { name: "annie", date: "1 / 6 / 23", confirmed: "yes", spent: 0 },
  { name: "annie", date: "1 / 6 / 23", confirmed: "no", spent: 2 },
  { name: "annie", date: "1 / 6 / 23", confirmed: "no", spent: 2 },
];

let try2 = inputArray.reduce((accumulator, current) => {
  if (!accumulator[current.name]) accumulator[current.name] = {
    spent: 0,
    confirmedAndNotSpent: 0,
    notConfirmedAndSpent: 0
  };
  
  accumulator[current.name].spent += current.spent;
  
  if(current.confirmed === "yes" && current.spent === 0) {
    accumulator[current.name].confirmedAndNotSpent++;
  }
  
  if(current.confirmed === "no") {
    accumulator[current.name].notConfirmedAndSpent++;
  }
  return accumulator;
}, {})

document.getElementById("out").innerText = JSON.stringify(try2, null, 4)
<pre id="out"></p>
Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading