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 allspent
for aname
- value of key
confirmedAndNotSpent
is just the addition of allconfirmed
as ‘yes’ butspent
as 0 for aname
- value of key
notConfirmedAndSpent
is just an addition of allconfirmed
as ‘no’ for aname
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.
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:
- 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;
- In JavaScript,
undefined + 0
(or any number) is equal to NaN. To solve this. You have to first initialize yourspent
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>