Reputation: 269
So I have a data like this
const carts = [
{
name: 'Voucher A',
participants: [
{
date: 112
},
{
date: 112
}
],
supplierName: 'ABC',
ticketDescription: 'Description of',
...data
},
{
name: 'Voucher B',
participants: [
{
date: 111
},
{
date: 112
}
],
supplierName: 'ABC',
ticketDescription: 'Description of',
...data
}
]
And I want to group it based on the date (if it has same date). So for data above, the expected result will be
expected = [
{
name: 'Voucher A',
date: 1,
count: 1,
supplierName: 'ABC',
ticketDescription: 'Description of',
...data
},
{
name: 'Voucher A',
date: 2,
count: 1,
supplierName: 'ABC',
ticketDescription: 'Description of',
...data
}
]
Because it has different date. But if it has same date, the expected result will be
expected = [
{
name: 'Voucher A',
date: 1,
count: 2,
supplierName: 'ABC',
ticketDescription: 'Description of',
...data
}
]
I was trying to use reduce to group it but it did not give the structure I want
carts.forEach(cart => {
cart.participants.reduce((acc, obj) => {
acc[obj.date] = [...acc[obj.date] || [], obj]
return acc
}, {})
})
Upvotes: 1
Views: 71
Reputation: 11001
Use forEach
and destructuring
const process = ({ participants, name }) => {
const res = {};
participants.forEach(({ date }) => {
res[date] ??= { name, count: 0, date };
res[date].count += 1;
});
return Object.values(res);
};
const carts = [
{
name: "Voucher A",
participants: [
{
date: 1,
},
{
date: 2,
},
],
},
];
console.log(carts.flatMap(process));
const carts2 = [
{
name: "Voucher A",
participants: [
{
date: 1,
},
{
date: 1,
},
],
},
];
console.log(carts2.flatMap(process));
Upvotes: 1
Reputation: 4470
If you want use, just plain for
loops, you can try this solution. It looks simple and elegant 😜😜
const carts = [
{
name: 'Voucher A',
participants: [
{
date: 1
},
{
date: 1
},
{
date: 2
}
]
},
{
name: 'Voucher B',
participants: [
{
date: 1
},
{
date: 2
},
{
date: 2
}
]
}
]
const finalOutput = []
for (const cart of carts) {
for (const participant of cart.participants) {
const res = finalOutput.find(e => e.name === cart.name && e.date === participant.date)
if (res) {
res.count += 1
} else {
finalOutput.push({ name: cart.name, date: participant.date, count: 1 })
}
}
}
console.log(finalOutput)
Upvotes: 1
Reputation: 370729
To organize the data, I think you need two associations to group by: the name and the dates and their counts for that name:
const carts = [
{
name: 'Voucher A',
participants: [
{
date: 1
},
{
date: 2
}
]
}
];
const groupedByNames = {};
for (const { name, participants } of carts) {
if (!groupedByNames[name]) groupedByNames[name] = {};
for (const { date } of participants) {
groupedByNames[name][date] = (groupedByNames[name][date] || 0) + 1;
}
}
const output = Object.entries(groupedByNames).flatMap(
([name, dateCounts]) => Object.entries(dateCounts).map(
([date, count]) => ({ name, date: Number(date), count })
)
);
console.log(output);
Upvotes: 1