Reputation: 2709
I have difficulties finding a way to map an array of objects, to a new array that will need to have objects defined by specific fields and values plus I also need to add objects by a single day, will explain details further down and I cannot use for loops of any kind due code style restriction I have in my project
The data I need to map to a new array
[
{
id: 'C12-TBX4',
studyId: 'TBX4',
siteId: 'USA-1',
statusType: 'INCOMPLETE',
statusFrom: '2020-12-01',
statusTo: '2020-12-05'
},
{
id: 'C13-TBX4',
studyId: 'TBX4',
siteId: 'USA-1',
statusType: 'INCOMPLETE',
statusFrom: '2020-12-03',
statusTo: '2020-12-07'
},
{
id: 'C14-TBX4',
studyId: 'TBX4',
siteId: 'USA-1',
statusType: 'INCOMPLETE',
statusFrom: '2020-12-05',
statusTo: '2020-12-08'
},
{
id: 'C15-TBX4',
studyId: 'TBX4',
siteId: null,
statusType: 'REJECTED',
statusFrom: '2020-12-05',
statusTo: '2020-12-08'
},
{
id: 'C16-TBX4',
studyId: 'TBX4',
siteId: null,
statusType: 'REJECTED',
statusFrom: '2020-12-05',
statusTo: '2020-12-09'
},
{
id: 'C17-TBX4',
studyId: 'TBX4',
siteId: 'USA-1',
statusType: 'DROPOUT',
eligible: true,
statusFrom: '2020-12-05',
statusTo: '2020-12-09'
},
{
id: 'C17-TBX4',
studyId: 'TBX4',
siteId: 'USA-1',
statusType: 'DROPOUT',
eligible: false,
statusFrom: '2020-12-05',
statusTo: '2020-12-10'
}
]
The above array needs to be compared and re-mapped using the following dates
[
2020-12-01T00:00:00.000Z,
2020-12-02T00:00:00.000Z,
2020-12-03T00:00:00.000Z,
2020-12-04T00:00:00.000Z,
2020-12-05T00:00:00.000Z,
2020-12-06T00:00:00.000Z,
2020-12-07T00:00:00.000Z,
2020-12-08T00:00:00.000Z,
2020-12-09T00:00:00.000Z
]
The dates are in a range from the minimum to the maximum date of the data object.
The data object contains an interval as statusFrom
and statusTo
; I need to have a new array of objects where we will have a single day from the dates object.
The array also will include a new field called total
which is the total of id
in a single study with the same statusType
on the same day.
To give an example of the result I need to have
[
// INCOMPLETE
{
"studyId": "TBX4",
"siteId": "USA-1",
"day": "2020-12-01",
"statusType": "INCOMPLETE",
"total": 1 // Only "id": "C12-TBX4",
},
{
"studyId": "TBX4",
"siteId": "USA-1",
"day": "2020-12-02",
"statusType": "INCOMPLETE",
"total": 1 // Only "id": "C12-TBX4",
},
{
"studyId": "TBX4",
"siteId": "USA-1",
"day": "2020-12-03",
"statusType": "INCOMPLETE",
"total": 2 // we have C13-TBX4 + C12-TBX4, dates are overlapping
},
{
"studyId": "TBX4",
"siteId": "USA-1",
"day": "2020-12-03",
"statusType": "INCOMPLETE",
"total": 2 // we have C13-TBX4 + C12-TBX4, dates are overlapping
},
{
"studyId": "TBX4",
"siteId": "USA-1",
"day": "2020-12-04",
"statusType": "INCOMPLETE",
"total": 2 // we have C13-TBX4 + C12-TBX4, dates are overlapping
},
{
"studyId": "TBX4",
"siteId": "USA-1",
"day": "2020-12-05", // we include only status from and exclude status to
"statusType": "INCOMPLETE",
"total": 2 // we have C13-TBX4 + C14-TBX4, dates are overlapping -- C12-TBX4 is excluded
},
{
"studyId": "TBX4",
"siteId": "USA-1",
"day": "2020-12-06",
"statusType": "INCOMPLETE",
"total": 2 // we have C13-TBX4 + C14-TBX4, dates are overlapping
},
{
"studyId": "TBX4",
"siteId": "USA-1",
"day": "2020-12-07",
"statusType": "INCOMPLETE",
"total": 1 // we have C14-TBX4
},
]
The above is just the example for the statusType: INCOMPLETE
but the same logic needs to be done for the other statuses.
As you see the goal is to map a new array based on single dates in a range of dates and add the total of how many ids are in that status on that day by a single day.
I do not include any snippets as honestly have no idea where to start and how to do it
Upvotes: 1
Views: 967
Reputation: 62686
If I understand properly, we're given studies that contain a range of days, and we're given a list of specific dates that the studies' ranges encompass. We want to produce study objects that indicate the specific day each contains, and do a little totaling based on matching days and types.
const data = [
{
id: "C12-TBX4",
studyId: "TBX4",
siteId: "USA-1",
statusType: "INCOMPLETE",
statusFrom: "2020-12-01",
statusTo: "2020-12-05"
},
{
id: "C13-TBX4",
studyId: "TBX4",
siteId: "USA-1",
statusType: "INCOMPLETE",
statusFrom: "2020-12-03",
statusTo: "2020-12-07"
},
{
id: "C14-TBX4",
studyId: "TBX4",
siteId: "USA-1",
statusType: "INCOMPLETE",
statusFrom: "2020-12-05",
statusTo: "2020-12-08"
},
{
id: "C16-TBX4",
studyId: "TBX4",
siteId: null,
statusType: "REJECTED",
statusFrom: "2020-12-05",
statusTo: "2020-12-09"
},
{
id: "C17-TBX4",
studyId: "TBX4",
siteId: null,
statusType: "REJECTED",
statusFrom: "2020-12-05",
statusTo: "2020-12-09"
},
{
id: "C18-TBX4",
studyId: "TBX4",
siteId: "USA-1",
statusType: "DROPOUT",
eligible: true,
statusFrom: "2020-12-05",
statusTo: "2020-12-09"
},
{
id: "C19-TBX4",
studyId: "TBX4",
siteId: "USA-1",
statusType: "DROPOUT",
eligible: false,
statusFrom: "2020-12-05",
statusTo: "2020-12-10"
}
];
const rangeOfDates = [
new Date("2020-12-01T00:00:00.000Z"),
new Date("2020-12-02T00:00:00.000Z"),
new Date("2020-12-03T00:00:00.000Z"),
new Date("2020-12-04T00:00:00.000Z"),
new Date("2020-12-05T00:00:00.000Z"),
new Date("2020-12-06T00:00:00.000Z"),
new Date("2020-12-07T00:00:00.000Z"),
new Date("2020-12-08T00:00:00.000Z"),
new Date("2020-12-09T00:00:00.000Z")
];
// prepare input objects for search by date
let studies = data.map((s) => {
let r = Object.assign({}, s);
// getTime() gives scalar ms since the epoch, for simpler comparisons
r.statusFrom = new Date(r.statusFrom).getTime();
r.statusTo = r.statusTo ? new Date(r.statusTo).getTime() : 8640000000000000;
return r;
});
// same for the times
let times = rangeOfDates.map((d) => {
let time = d.getTime();
let day = d.toISOString().split("T")[0]; // the day part of the string
return { time, day };
});
let resultIndex = {};
times.forEach((t) => {
// get the matching studies, recall that t is an epoch time and a day string
let matchingStudies = studies.filter(s => {
return s.statusFrom <= t.time && t.time < s.statusTo;
});
let idIndex = {};
// particularize the matching studies with the matching day, and requiring a unique studyId-day
matchingStudies.forEach(ms => {
let r = {
day: t.day,
studyId: ms.studyId,
siteId: ms.siteId,
statusType: ms.statusType,
total: 0
};
// require uniqueness of studyId-day, second input prevails
let key = `${r.day}${r.studyId}`;
idIndex[key] = r;
});
matchingStudies = Object.values(idIndex);
// summarize totals by statusType-day
matchingStudies.forEach(ms => {
let key = `${ms.day}${ms.statusType}`;
if (!resultIndex[key]) resultIndex[key] = ms;
resultIndex[key].total++;
})
});
let result = Object.values(resultIndex);
console.log(result);
Upvotes: 1