Remove duplicates from an array of objects based on time created

Viewed 135

I have an array of objects and there are some duplicate objects

const data = [
{
    "id": "1011",
    "name": "abc",
    "Dob": "3/2/11",
    "timeCreated": "16:03:41"
},
{
    "id": "1012",
    "name": "xys",
    "Dob": "6/5/12",
    "timeCreated": "01:05:21"
},
{
    "id": "1011",
    "name": "xyz",
    "Dob": "3/2/11",
    "timeCreated": "17:03:41"
},
{
    "id": "1011",
    "name": "xyz",
    "Dob": "3/2/11",
    "timeCreated": "15:03:41"
}
]

I am removing duplicates in the array by using some()

let arr = [];
data.forEach(obj => {
  if (!arr .some(o => o.id === obj.id)) {
    arr.push({ ...obj})
  }
});   

I need help filtering it and only keeping the latest object based off of "timeCreated"

so the data looks something like this:

{
    "id": "1012",
    "name": "xys",
    "Dob": "6/5/12",
    "timeCreated": "01:05:21"
},
{
    "id": "1011",
    "name": "xyz",
    "Dob": "3/2/11",
    "timeCreated": "17:03:41"
},
]
2 Answers

you can do that :

const data = 
  [ { id: '1011', name: 'abc', Dob: '3/2/11', timeCreated: '16:03:41' } 
  , { id: '1012', name: 'xys', Dob: '6/5/12', timeCreated: '01:05:21' } 
  , { id: '1011', name: 'xyz', Dob: '3/2/11', timeCreated: '17:03:41' } 
  , { id: '1011', name: 'xyz', Dob: '3/2/11', timeCreated: '15:03:41' } 
  ] 

const arr = data.reduce((result,obj)=>
  {
  let row = result.find(x=>x.id===obj.id)
  if (!row)
         result.push({...obj})
  else if (row.timeCreated < obj.timeCreated)
         Object.assign(row,obj)
  return result
  },[])

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

Late to the party, but here's a shorter, maybe faster, more efficient solution that just involves a sort and filter operation

let tmp=[], arr = data.sort((a, b) => +b.timeCreated.replaceAll(':', '') - +a.timeCreated.replaceAll(':', ''))
            .filter(o => (!tmp.includes(o.id) && tmp.push(o.id)));

How it works: Pretty simply actually. It first sorts the array by timeCreated descending. It does this by (on the fly) transforming the 'HH:MM:SS' string into the number HHMMSS (+b.timeCreated.replaceAll(':', '')), then comparing. Then it takes the sorted array and filters it through the temporary array tmp, which stores ids each iteration - and if the id is already in there (and we know that is the latest according to the timeCreated) we filter it out. This is all handled by the wonderfully simple ternary: .filter(o => (!tmp.includes(o.id) && tmp.push(o.id)), which says if we've already seen that id, return false, otherwise make a note of it

Why it's cool - For most use cases (small data sets), there isn't a significant difference between functional iterators like map, reduce, forEach, filter, sort - however this is thinking out of the box. Rather than build datasets and reduce them down, this smartly chops it to size first - using only 2 operations.

const data = [{ id: '1011', name: 'abc', Dob: '3/2/11', timeCreated: '16:03:41' }, { id: '1012', name: 'xys', Dob: '6/5/12', timeCreated: '01:05:21' }, { id: '1011', name: 'xyz', Dob: '3/2/11', timeCreated: '17:03:41' }, { id: '1011', name: 'xyz', Dob: '3/2/11', timeCreated: '15:03:41' }]
let tmp=[], arr = data.sort((a, b) => +b.timeCreated.replaceAll(':', '') - +a.timeCreated.replaceAll(':', '')).filter(o => (!tmp.includes(o.id) && tmp.push(o.id)));
    
console.log(arr)

Related