1

I have an array of objects that include a startDate. The objects are not in order of startDate. I want to create a new array and group all objects that share the same startDate into separate objects.

var eventArray = [
  {
    eventName: "event1",
    startDate: "2018/08/01", // YYYY/MM/DD
    id: 1
  },
  {
    eventName: "event2",
    startDate: "2018/08/03",
    id: 2
  },
  {
    eventName: "event3",
    startDate: "2018/08/01",
    id: 3
  },
  {
    eventName: "event4",
    startDate: "2018/08/06",
    id: 4
  }
];

Using angular.forEach I've tried looping through all the objects, getting the startDate value, adding that value to a new array, and adding the current object to the array where it has a matching date. I cannot find a solution to add the current event object to the object that exists in the new array (eventDays) at the index that matches my eventIndex variable.

let eventDays = [];
let eventIndex = 0;

angular.forEach(eventArray, function(event){
  let day = event.startDate;

  if(eventDays.length == 0){
    eventDays.push({
      dateGroup: day,
      event
    });
  }
  else {
    if(event.startDate == eventDays[eventIndex].groupDay) {
      // insert event object into eventDays[eventIndex] after dateGroup, event
    }
    else if(event.startDate !== eventDays[eventIndex].groupDay){
      eventDays.push({
        dateGroup: day,
        event
      });

      eventIndex++;
    }
  }

});

The result I'm looking for is something like this.

eventDays  = [
  {
    groupDate: "2018/08/01",
    event: {
      eventName: "event1",
      startDate: "2018/08/01",
      id: 1
    },
    event: {
      eventName: "event3",
      startDate: "2018/08/01",
      id: 3
    }
  },
  {
    groupDate: "2018/08/03",
    event: {
      eventName: "event2",
      startDate: "2018/08/03",
      id: 2
    }
  },
  {
    groupDate: "2018/08/06",
    event: {
      eventName: "event4",
      startDate: "2018/08/06",
      id: 4
    }
  }
];

Is something like this possible?

UPDATE

Nina is right, I cannot reuse the name keyname. I need to create another array within the object to store the objects I'm passing over. This snippet is working.

angular.forEach($scope.events, function (event) {

            if ($scope.eventDays.length == 0) {
                $scope.eventDays.push({
                    'groupDate': event.startDate,
                    'events': [event]
                });
            } else {
                if (event.startDate == $scope.eventDays[eventIndex].groupDate) {
                    $scope.eventDays[eventIndex].events.push(event)
                } else if (event.startDate !== $scope.eventDays[eventIndex].groupDate) {
                    $scope.eventDays.push({
                        'groupDate': event.startDate,
                        'events': [event]
                    });

                    eventIndex++;
                }
            }

        });
6
  • 1
    no, you can not have the same keyname twice. you could take an array for collecting the objects. Commented Jul 24, 2018 at 19:24
  • Nina is correct, it should be something like groupDate: '2018/08/03', events: [{eventName: "event1", startDate: "2018/08/01", id: 1},{eventName: "event3",startDate: "2018/08/01",id: 3}] then you can just change the way you get them slightly. It would be looping through events in an array instead of having top level objects. This is also a better way to format JSON data. Commented Jul 24, 2018 at 19:30
  • frostbyte, FYI, @NinaScholz refers to the keyname event. You have to think about any other output alternative. When you do so, update the question. Commented Jul 24, 2018 at 19:31
  • Nina it totally right. I'm ashamed I missed that. I've made an update to my post. I'm adding the current event to an events array. This is working! Commented Jul 24, 2018 at 20:08
  • If you have an answer for your question, don't add it to the question. Put it in the answer section. See Can I answer my own question?, Commented Jul 24, 2018 at 21:45

2 Answers 2

2

You could take a Map for grouping the same startDate and render than the array with the objects.

var eventArray = [{ eventName: "event1", startDate: "2018/08/01", id: 1 }, { eventName: "event2", startDate: "2018/08/03", id: 2 }, { eventName: "event3", startDate: "2018/08/01", id: 3 }, { eventName: "event4", startDate: "2018/08/06", id: 4 }],
    result = Array.from(
        eventArray.reduce((m, o) => m.set(o.startDate, (m.get(o.startDate) || []).concat(o)), new Map),
        ([groupDate, events]) => ({ groupDate, events })
    );

console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

Sign up to request clarification or add additional context in comments.

1 Comment

I'm not familiar with using Map in JS. Your solution is a lot cleaner than mine. I'm going to play around with your solution and see if I can get it working. Thanks!
1

Nina is right, I cannot reuse the name keyname. I need to create another array within the object to store the objects I'm passing over. This snippet is working.

angular.forEach($scope.events, function (event) {

        if ($scope.eventDays.length == 0) {
            $scope.eventDays.push({
                'groupDate': event.startDate,
                'events': [event]
            });
        } else {
            if (event.startDate == $scope.eventDays[eventIndex].groupDate) {
                $scope.eventDays[eventIndex].events.push(event)
            } else if (event.startDate !== $scope.eventDays[eventIndex].groupDate) {
                $scope.eventDays.push({
                    'groupDate': event.startDate,
                    'events': [event]
                });

                eventIndex++;
            }
        }

    });

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.