Search code examples
javascriptarrayobject

Reduce an Array of Objects With Duplicate IDs by a Second Date Property


I have an array of objects and all of them have at least 1 other object with the same ID. I am trying to reduce this array to only return the object with the most recent date. An example array of what I'm dealing with:

var arrObj = [
   {id: 1, startDate: 2019-10-09},
   {id: 1, startDate: 2019-10-05},
   {id: 1, startDate: 2019-09-30},
   {id: 2, startDate: 2018-08-05},
   {id: 2, startDate: 2018-09-05}
]

Output I am trying to achieve:

var newArrObj = [
   {id: 1, startDate: 2019-10-09},
   {id: 2, startDate: 2018-09-05}
]

I have found a lot of examples of reducing or removing duplicate objects by ID completely, but I can't seem to find an example of first identifying the objects with the same ID, then reducing by a second property. Unfortunately I keep finding myself creating a lot of nested for loops. Is there an elegant way to do this? I need to be able to do it in ES5 or earlier.

var uniqueIDs = [];
for (a in arrObj) {
  if(uniqueIDs.indexOf(arrObj[a].id) != -1) {
     uniqueIDs.push(arrObj[a].id);
  }
}

var newArrObj = [];
for(b in uniqueIDs) {
  var uniqueId = uniqueIDs[b];
  var uniqueIdObjs = arrObj.filter(function(x) {
    return x.id === uniqueId;
  });
  for(c in uniqueIdObjs) {
    var objDate = uniqueIdObjs[c].startDate;
    //This is where I get stuck
  }
}

Solution

  • I'd go with your style of first filtering the IDs to uniques, because thats the easy part. Then you can simply chain array function so extract the last date:

    1. map over the unique IDs so that your returns create a new array at the end.

    2. filter the original array to include only object with the ID we workin on now

    3. sort the temporary array created with all objects of the same ID so that the mostrecent one would be first, and return the first element.

      let finalResult = uniqueIDs.map( id => {
         return arrayObj.filter( obj => obj.id === id )
          .sort((a, b) => new Date(b.startDate) - new Date(a.startDate))[0];
      

    Tada! finalResult is now and array containing only one object with the most recent date for every ID :)