I asked a similar question here Transform an Array into an Object using .reduce(), however I am trying to find an alternative solution with findIndex.
This input data:
const reports = [
{
dateOfReport: "11-01-2021",
userId: "id1",
userMetric: { first_metric: 10, second_metric: 15 },
},
{
dateOfReport: "11-01-2021",
userId: "id2",
userMetric: { first_metric: 9, second_metric: 14 },
},
{
dateOfReport: "12-01-2021",
userId: "id1",
userMetric: { first_metric: 11, second_metric: 14 },
},
{
dateOfReport: "12-01-2021",
userId: "id2",
userMetric: { first_metric: 16, second_metric: 19 },
},
];
Output data must be:
const output = [
{
dateOfReport: "11-01-2021",
id1: { first_metric: 10, second_metric: 15 },
id2: { first_metric: 9, second_metric: 14 },
},
{
dateOfReport: "12-01-2021",
id1: { first_metric: 11, second_metric: 14 },
id2: { first_metric: 16, second_metric: 19 },
},
];
I tried to write similar code below, but I get duplicate data in the output. Can anyone help solve this problem?
const groupedReports = reports.reduce((acc, dataItem) => {
const nodeIndex = acc.findIndex((item) => item.dateOfReport === dataItem.dateOfReport);
const newNode = { date: dataItem.date, [dataItem.userId]: dataItem.userMetric };
console.log("NEW NODE", newNode);
return [...acc.slice(0, nodeIndex - 1), newNode, ...acc.slice(nodeIndex 1)]
}, []);
CodePudding user response:
I think your can do like this:
reports.reduce((pre, cur) => {
let index = pre.findIndex(item => item.dateOfReport == cur.dateOfReport)
if (index != -1) {
pre[index][cur.userId] = cur.userMetric
} else {
pre.push({
dateOfReport: cur.dateOfReport,
[cur.userId]: cur.userMetric
})
}
return pre
}, [])
CodePudding user response:
Here's my solution:
const reports = [
{
dateOfReport: "11-01-2021",
userId: "id1",
userMetric: { first_metric: 10, second_metric: 15 },
},
{
dateOfReport: "11-01-2021",
userId: "id2",
userMetric: { first_metric: 9, second_metric: 14 },
},
{
dateOfReport: "12-01-2021",
userId: "id1",
userMetric: { first_metric: 11, second_metric: 14 },
},
{
dateOfReport: "12-01-2021",
userId: "id2",
userMetric: { first_metric: 16, second_metric: 19 },
},
];
const sortReports = (reports) => {
// Array of dates with no duplicates
const dates = [...new Set(reports.map(el => el.dateOfReport))];
// Replace each date with an array of reports that are relevant to the date
// Reduce each array of reports into an object with your desired format
const newReports = dates
.map(date => reports
.filter(report => report.dateOfReport === date)
.reduce(el => ({
dateOfReport: el.dateOfReport,
[el.userId]: el.userMetric
})));
return newReports;
}
console.log(sortReports(reports));
CodePudding user response:
You could take an object for grouping and assign the new properties to the id.
const
reports = [{ dateOfReport: "11-01-2021", userId: "id1", userMetric: { first_metric: 10, second_metric: 15 } }, { dateOfReport: "11-01-2021", userId: "id2", userMetric: { first_metric: 9, second_metric: 14 } }, { dateOfReport: "12-01-2021", userId: "id1", userMetric: { first_metric: 11, second_metric: 14 } }, { dateOfReport: "12-01-2021", userId: "id2", userMetric: { first_metric: 16, second_metric: 19 } }],
result = Object.values(reports.reduce((r, { dateOfReport, userId, userMetric }) => {
(r[dateOfReport] ??= { dateOfReport })[userId] = userMetric;
return r;
}, {}));
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>