简体   繁体   中英

How to map data to a new array with specific fields and values and add a single object per day based on a range of dates

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

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);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM