I have the following snippet which uses a reduce and I cannot use another kind of loops, I have as a requirement to solve this by a reduce or a way which does not include a loop as for or forEach
As you will see I have an array of objects and inside it, I have 2 objects with the same studyId.
What I need is to merge the objects with the same studyId and the subfield siteIds in one array to have the following result
{ studyId: "ANNO5", siteIds: ["Paris", "Bon", "PLACEHOLDER", "Amsterdam", "Bruxelles" ] }
The siteIds also need to be unique I cannot have repeated the same siteId in the array
In the snippet, I tried with the reducer as I have that as a requirement but cannot figure out how to achieve the result I need.
Including the full desired output as was confusing a super comments
[
// Here the merged with the same StudyId
{ studyId: "ANNO5", siteIds: ["Paris", "Bon", "PLACEHOLDER", "Amsterdam", "Bruxelles", "Paris"] },
{
studyId: "ANNO6",
siteIds: ["Rome", "Torino", "PLACEHOLDER", "Milano"]
},
{ studyId: "ANNO7", siteIds: undefined },
{ studyId: "ANNO8", siteIds: undefined }
];
as per undefined the requirement is similar to having something like this
siteIds: isEmpty(siteIds) ? undefined : uniq(siteIds),
When no siteIds we have undefined as per the above example
>Solution :
You can group the data by studyId using reduce and use Set to remove duplicate siteIds.
const siteIds = [
{ studyId: "ANNO5", siteIds: ["Paris", "Bon", "PLACEHOLDER"] },
{ studyId: "ANNO5", siteIds: ["Amsterdam", "Bruxelles", "PLACEHOLDER", "Paris"] },
{ studyId: "ANNO6", siteIds: ["Rome", "Torino", "PLACEHOLDER", "Milano"] },
{ studyId: "ANNO7", siteIds: undefined },
{ studyId: "ANNO8", siteIds: undefined },
];
const result = Object.values(
siteIds.reduce((r, o) => {
if (!r[o.studyId]) {
r[o.studyId] = { ...o, siteIds: undefined };
}
if (o.siteIds) {
(r[o.studyId].siteIds ??= []).push(...o.siteIds);
r[o.studyId].siteIds = [...new Set(r[o.studyId].siteIds)];
}
return r;
}, {})
);
console.log(result);
If you want to avoid creating sets in every iteration, then refer to the snippet below:
const siteIds = [
{ studyId: "ANNO5", siteIds: ["Paris", "Bon", "PLACEHOLDER"] },
{ studyId: "ANNO5", siteIds: ["Amsterdam", "Bruxelles", "PLACEHOLDER", "Paris"] },
{ studyId: "ANNO6", siteIds: ["Rome", "Torino", "PLACEHOLDER", "Milano"] },
{ studyId: "ANNO7", siteIds: undefined },
{ studyId: "ANNO8", siteIds: undefined },
];
const result = Object.values(
siteIds.reduce((r, o) => {
if (!r[o.studyId]) {
r[o.studyId] = { ...o, siteIds: undefined };
}
if (o.siteIds) {
(r[o.studyId].siteIds ??= []).push(...o.siteIds);
}
return r;
}, {})
).map((o) => ({
...o,
...(o.siteIds && { siteIds: [...new Set(o.siteIds)] }),
}));
console.log(result);