skip to Main Content

I wrote code to remove the duplicates from an array, but I feel it could be made more elegant. Suggestions Please.

Interface Definition
export interface SomeClass {
  version: number,
  typeDescription: string
}
Test Data
sthClass: SomeClass[] = [
  { typeDescription: "typeA", version: 10 },
  { typeDescription: "typeA", version: 21 },
  { typeDescription: "typeB", version: 101 },
  { typeDescription: "typeC", version: 199 },
  { typeDescription: "typeA", version: 220 },
  { typeDescription: "typeB", version: 33 },
  { typeDescription: "typeA", version: 15},
];
Business Logic to Remove duplicates and keep the one that has largest version number
for (let index = this.sthClass.length - 1; index >= 0; index--) {
  filterArr = this.sthClass.filter(item => item.typeDescription == this.sthClass[index].typeDescription);

  if (filterArr.length > 1) {
    //sort in Desc Order
    filterArr.sort((a: SomeClass, b: SomeClass) => b.version - a.version);

    let idx = this.sthClass.findIndex(k => filterArr[1] === k)
    this.sthClass.splice(idx, 1);
  }
}

2

Answers


  1. One way to do it in linear time is using reduce() and a JS obejct (alternatively a Map) to efficiently lookup whether a typeDescription with that value has already been encountered and if it was whether the version of the current item is higher. Finally you can then obtain the values using Object.values().

    const sthClass = [
        { typeDescription: "typeA", version: 10 },
        { typeDescription: "typeA", version: 21 },
        { typeDescription: "typeB", version: 101 },
        { typeDescription: "typeC", version: 199 },
        { typeDescription: "typeA", version: 220 },
        { typeDescription: "typeB", version: 33 },
        { typeDescription: "typeA", version: 15 },
    ];
    
    const output = Object.values(sthClass.reduce((acc, cur) => {
        if (!Object.hasOwn(acc, cur.typeDescription)) {
            acc[cur.typeDescription] = cur;
            return acc;
        }
        if (cur.version > acc[cur.typeDescription].version) {
            acc[cur.typeDescription] = cur
        }
        return acc;
    }, {}));
    
    console.log(output);
    .as-console-wrapper {
        max-height: 100% !important;
        top: 0;
    }

    Alternatively:

    A working, yet slower (O(n log n) compared to O(n) above) and to my mind also less elegant solution using sorting can also be created.

    1. Sort by typeDescription and then version in descending order
    2. Only ever keep the first element of a group by keeping track of the previous typeDescription
    const sthClass = [
        { typeDescription: "typeA", version: 10 },
        { typeDescription: "typeA", version: 21 },
        { typeDescription: "typeB", version: 101 },
        { typeDescription: "typeC", version: 199 },
        { typeDescription: "typeA", version: 220 },
        { typeDescription: "typeB", version: 33 },
        { typeDescription: "typeA", version: 15 },
    ];
    
    
    sthClass.sort((a, b) => a.typeDescription.localeCompare(b.typeDescription) || b.version - a.version);
    let previous = undefined;
    const output2 = sthClass.reduce((acc, cur) => {
        if (cur.typeDescription !== previous) {
            acc = [...acc, cur]
        }
        previous = cur.typeDescription;
        return acc;
    }, []);
    console.log(output2);
    .as-console-wrapper {
        max-height: 100% !important;
        top: 0;
    }

    The alternative variant is only slower due to sorting which generally can’t be done quicker than in O(n log n) but if due to your data you know you can sort in linear time using some specialized algorithm, this solution might be faster/ more memory efficient.

    Login or Signup to reply.
  2. Here is my Solution:-

    1. Initialize an empty object obj.
    2. Loop through each object in the sthClass array.
    3. Check if the typeDescription property of the current object exists in the obj.
    4. If it does, compare the version property of the current object with the existing value in obj for the same typeDescription. If the version of the current object is larger, update the value in obj for the typeDescription with the version of the current object.
    5. If it doesn’t exist, add the typeDescription and version of the current object to obj.
    6. After the loop finishes, the obj will contain the unique typeDescription and largest version for each typeDescription.

    The output of the code will be an object that contains unique typeDescription as keys and the largest version number for each typeDescription as values.

    let sthClass = [
      { typeDescription: "typeA", version: 10 },
      { typeDescription: "typeA", version: 21 },
      { typeDescription: "typeB", version: 101 },
      { typeDescription: "typeC", version: 199 },
      { typeDescription: "typeA", version: 220 },
      { typeDescription: "typeB", version: 33 },
      { typeDescription: "typeA", version: 15},
    ];
    
    let obj = {};
    
    for(let i = 0; i<sthClass.length; i++){
      if(obj[sthClass[i].typeDescription]){
        obj[sthClass[i].typeDescription] = obj[sthClass[i].typeDescription] < sthClass[i].version ? sthClass[i].version : obj[sthClass[i].typeDescription];
      } else {
        obj[sthClass[i].typeDescription] = sthClass[i].version;
      }
    }
    
    console.log(obj);
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search