Remove duplicates by date in typescript

Issue

I have a list of objects order by date. Each object have the folling structure

export class SegmentDTO  {
  dateInsert: Date;
  dateModified: Date;
  id: number;
  language: number;
  content: string;
}

I want to get the disctincs object based on language property, and take the most recent one of each language (based on dateModified)

What I tried is this:

const listLangOrderByDateASC = this.segments.sort((a, b) => new Date(a.dateInsert).getTime() - new Date(b.dateInsert).getTime());

 const result = [...new Map(listSourceLangOrderByDateASC.map(item => [item.language, item])).values()];

With this, I can obtain the most recent object for each language, but I don’t know if there is a better approach to do it. I discover that making this takes the final objects of the sorted list, but I don’t really know if it’s just lucky.

Any help would be aprecciated!

Solution

You could use Array.reduce() to get the most recently modified items, grouped by language.

We’ll create an object, with a key for each language. If the object has no value at the language key or the value has an older modified date, we’ll replace with the new entry.

Once we’ve grouped the items, we’ll convert to an array again with Object.values()

let segments = [ { dateInsert: new Date('2022-06-01T07:00:00Z'), dateModified: new Date('2022-06-02T09:00:00Z'), id: 1, language: 1, content: 'Content', }, { dateInsert: new Date('2022-06-01T07:00:00Z'), dateModified: new Date('2022-06-02T11:00:00Z'), id: 1, language: 1, content: 'Content', }, { dateInsert: new Date('2022-06-01T07:00:00Z'), dateModified: new Date('2022-06-02T14:00:00Z'), id: 1, language: 2, content: 'Content', }, { dateInsert: new Date('2022-06-01T07:00:00Z'), dateModified: new Date('2022-06-01T19:00:00Z'), id: 1, language: 2, content: 'Content', } ];

const result = Object.values(segments.reduce((acc, obj) => { 
    if (!acc[obj.language] || (acc[obj.language].dateModified < obj.dateModified)) {
        acc[obj.language] = obj;
    }
    return acc;
}, {}));
console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }

We can also do this with a Map object:

const segments = [ { dateInsert: new Date('2022-06-01T07:00:00Z'), dateModified: new Date('2022-06-02T09:00:00Z'), id: 1, language: 1, content: 'Content', }, { dateInsert: new Date('2022-06-01T07:00:00Z'), dateModified: new Date('2022-06-02T11:00:00Z'), id: 1, language: 1, content: 'Content', }, { dateInsert: new Date('2022-06-01T07:00:00Z'), dateModified: new Date('2022-06-02T14:00:00Z'), id: 1, language: 2, content: 'Content', }, { dateInsert: new Date('2022-06-01T07:00:00Z'), dateModified: new Date('2022-06-01T19:00:00Z'), id: 1, language: 2, content: 'Content', } ];

const result = [...segments.reduce((acc, obj) => {
    if ((!acc.has(obj.language) || (acc.get(obj.language).dateModified) < obj.dateModified)) {
        acc.set(obj.language, obj);
    }
    return acc;
}, new Map()).values()];
console.log('Result:', result)
.as-console-wrapper { max-height: 100% !important; }

Answered By – Terry Lennox

Answer Checked By – Candace Johnson (AngularFixing Volunteer)

Leave a Reply

Your email address will not be published.