Group object values by date

Viewed 90

I'm trying to make an upcoming event on react native, I have this object

const calendatData = [
        {
            "data": [
              {
                "id": 25,
                "title": "Spotify",
                "name": "Family",
                "service_id": 1,
                "repetition": "Monthly",
                "price": "79000",
                "upcoming_date": [
                  "2020-08-07T13:35:44.606Z"
                ]
              },
              {
                "id": 26,
                "title": "Netflix",
                "name": "Mobile",
                "service_id": 2,
                "repetition": "Monthly",
                "price": "49000",
                "upcoming_date": [
                  "2020-08-18T13:35:44.600Z",
                  "2020-08-07T13:35:44.606Z"
                ]
              },
              {
                "id": 27,
                "title": "iTunes",
                "name": "Weekly Special",
                "service_id": 3,
                "repetition": "Weekly",
                "price": "22000",
                "upcoming_date": [
                  "2020-08-07T13:35:44.606Z",
                  "2020-08-14T13:35:44.606Z",
                  "2020-08-21T13:35:44.606Z",
                  "2020-08-28T13:35:44.606Z"
                ]
              }
            ],
            "status": "success"
          }
    ]

what I've been trying to do is to extract that object based on the upcoming_date. the result that I need is like this

upcomingData = [
        {
            date: '2020-08-07',
            title: [
                'Spotify',
                'Netflix',
                'iTunes'
            ]
        },
        {
            date: '2020-08-18',
            title: ['Netflix']
        },
        {
            date: '2020-08-14',
            title: ['iTuunes']
        },
        {
            date: '2020-08-21',
            title: ['iTuunes']
        },
        {
            date: '2020-08-28',
            title: ['iTuunes']
        }
]

On the same date, if there are multiple titles, it should be grouped under the same date in the object.

instead what I got was this object

upcomingData = [
    {
        title: [
            "Spotify",
            "Netflix",
            "iTunes",
        ],
        date : [
            "2020-08-29",
            "2020-08-07",
            "2020-08-18",
            "2020-08-07",
            "2020-08-07",
            "2020-08-14",
            "2020-08-21",
            "2020-08-28",
        ]
    }
]

I am new to this, and I'm aware that this is mostly about javascript knowledge, any help would be appreciated.

thanks

2 Answers

The ideas are:

  • First, iterate your object by Array.prototype.map() and set a unique map key from the converted date.
  • Then push the title to every map's key.

Actually your final map(here is myMap) will be your expected upcomingData. To output as your expected object, you can make it in your own way.

const calendarData = [{ "data": [{ "id": 25, "title": "Spotify", "name": "Family", "service_id": 1, "repetition": "Monthly", "price": "79000", "upcoming_date": ["2020-08-07T13:35:44.606Z"] }, { "id": 26, "title": "Netflix", "name": "Mobile", "service_id": 2, "repetition": "Monthly", "price": "49000", "upcoming_date": ["2020-08-18T13:35:44.600Z", "2020-08-07T13:35:44.606Z"] }, { "id": 27, "title": "iTunes", "name": "Weekly Special", "service_id": 3, "repetition": "Weekly", "price": "22000", "upcoming_date": ["2020-08-07T13:35:44.606Z", "2020-08-14T13:35:44.606Z", "2020-08-21T13:35:44.606Z", "2020-08-28T13:35:44.606Z"] }], "status": "success" }];

var myMap = new Map();

calendarData[0].data.map(element => {

    var dates = [];

    element.upcoming_date.map(date => {

        var upcoming_date = date.slice(0,10);

        if (!myMap.get(upcoming_date)) {
            myMap.set(upcoming_date, []);
        }

        dates.push(upcoming_date);

    });

    var len = dates.length;

    for (let i = 0; i < len; i++) {
        myMap.get(dates[i]).push(element.title);
    }
});

var upcomingData = [];

for (const entry of myMap.entries()) {
    var obj = {};
    obj["date"] = entry[0];
    obj["title"] = entry[1];
    upcomingData.push(obj);
}

console.log(upcomingData);

You may

  • traverse your source array with Array.prototype.reduce() building up the Map where trimmed portion of your date string is used as a key and the object of desired format as a value
  • extract Map values, using Map.prototype.values() into resulting array

Following is a quick live demo:

const src = [{"data":[{"id":25,"title":"Spotify","name":"Family","service_id":1,"repetition":"Monthly","price":"79000","upcoming_date":["2020-08-07T13:35:44.606Z"]},{"id":26,"title":"Netflix","name":"Mobile","service_id":2,"repetition":"Monthly","price":"49000","upcoming_date":["2020-08-18T13:35:44.600Z","2020-08-07T13:35:44.606Z"]},{"id":27,"title":"iTunes","name":"Weekly Special","service_id":3,"repetition":"Weekly","price":"22000","upcoming_date":["2020-08-07T13:35:44.606Z","2020-08-14T13:35:44.606Z","2020-08-21T13:35:44.606Z","2020-08-28T13:35:44.606Z"]}],"status":"success"}],
    
    result = [...src[0].data
      .reduce((r,{upcoming_date, title}) => (
         upcoming_date.forEach((s,_,__,date=s.slice(0,10)) =>
            r.set(
              date, 
              {date, title: [...(r.get(date)?.title||[]), title]}
            )),r),
         new Map())
      .values()
    ]
    
console.log(result)
.as-console-wrapper{min-height:100%;}

Related