Enhancing Code: Eliminate Duplicates from an Array

I have a code that removes duplicates from an array, but I believe it could be improved for better elegance. Any suggestions?

Interface Definition
export interface SomeClass {
  version: number,
  typeDescription: string
}
Test Data
someClasses: 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 with the highest version number
for (let index = this.someClasses.length - 1; index >= 0; index--) {
  filterArr = this.someClasses.filter(item => item.typeDescription == this.someClasses[index].typeDescription);

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

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

Answer №1

There's a efficient way to accomplish this in linear time by utilizing the reduce() method and a JavaScript object (or alternatively a Map) to effectively check if a typeDescription with a specific value has been encountered before, and if so, compare the versions to determine which one is higher. The final step involves extracting 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:

An additional method that works but is slower (O(n log n) compared to O(n) above) and may appear less elegant utilizes sorting.

  1. Sort by typeDescription and then version in descending order
  2. Maintain only the first element of each group by monitoring 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 approach is slightly slower due to sorting, typically performing at O(n log n), but offers potential speed/memory improvements if specialized algorithms can be used for linear-time sorting based on your data characteristics.

Answer №2

Here is the Approach:-

  1. Create an empty object called obj.
  2. Iterate through each element in the sthClass array.
  3. Check if the typeDescription property of the current element exists in the obj.
  4. If it exists, compare the version property of the current element with the existing value in obj for the same typeDescription. If the version of the current element is higher, update the value in obj for the typeDescription with the version of the current element.
  5. If it does not exist, add the typeDescription and version of the current element to obj.
  6. Once the iteration is complete, obj will contain the distinct typeDescription and highest version for each typeDescription.

The result of the code will be an object featuring unique typeDescriptions as keys and their corresponding highest version number 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);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

An import error was encountered: The module 'react-router-dom' does not export the component 'Navlink'

import React, { Component } from 'react'; import { Navbar, NavbarBrand, Nav, NavbarToggler, Collapse, NavItem, Jumbotron } from 'reactstrap'; import { NavLink } from 'react-router-dom'; I have added the router using the follo ...

WebSocket connection issues are being experienced by certain users

While using socket.io, I encountered an issue where some users were unable to send messages with the message "I can't send a message why?". After researching the problem, it seems that the firewall or antivirus software may be blocking websockets. If ...

How can I automatically direct my NodeJS application to the login screen?

Here is the setup of my project structure: There is a simple folder called static, within which I have: index.html (the homepage for user registration) login.html (the login page) In the parent folder, there is a file named server.js: // NodeJS code for ...

Using JavaScript, learn how to extract query parameters and encoded information from a URI

I am looking for a specific module in order to extract information from query parameters within a URL. The format includes 2 query parameters and an encoded piece of data. Do I need to use split functions or is there a more direct approach available? Sampl ...

TS18047 jest error: "object may be null"

I'm currently working on a test (jtest) for an angular component, but it keeps failing due to this particular error. Any thoughts on how to resolve this? :) it("should require valid email", () => { spectator.component.email.setValue( ...

Accessing a Parent Object's Method Within a ForEach Loop

While this question leans towards a JavaScript issue rather than Angular, the context remains within Angular. The problem arises when attempting to call the doSomething method from lodash's ._forEach, which creates its own scope causing an inability t ...

Starting a new React project

prtScn I'm encountering an issue while trying to initiate a new react app in Visual Studio Code. I have been following the given instructions as follows: in the visual code terminal : create-react-app sali (sali is the name) npm install node node_m ...

I'm curious if there are any APIs available in both the browser and Node.js that can efficiently convert a base64 string to a utf8

const decodeBase64ToUtf8 = (encodedString) => Buffer.from(encodedString, 'base64').toString('latin1') Is there a versatile API that can handle base64 to utf8 conversion seamlessly in both Node.js and web browsers? In Node.js, you c ...

What is the best way to access a ViewChild element in the parent component without rendering it?

I am currently utilizing a component within another component in the following manner: <inline-help> <help-title>{{::'lang.whatIsThis'|i18n}}</help-title> <help-body i18n="lang.helpBody">& ...

Creating an MVC actionlink in Javascript based on certain conditions

When a JsonResult of success is returned in VB.NET MVC 3 Razor view, I want to conditionally build an actionlink if data.Object.Status == 'Completed'; I have searched for a solution but nothing seems to fit. Here is what the actionlink should lo ...

Using Axios for Multiple Layers of API Requests within React

I have scoured numerous forums and articles, but the code still refuses to work as expected. While I am able to log the proper data, setting the State results in an empty object for some reason. After spending hours on this, it is entirely possible that I ...

Node.js redirection techniques

Node JS is still very new to me and I'm having trouble redirecting buttons to another page. Every time I attempt to redirect, I receive a "cannot GET /(the page that I am trying to redirect to)" error message. The code snippet I'm using for redir ...

Toggle the visibility of Div 1 and Div 2 with a click of the same button

Apologies for my lackluster title, but I couldn't come up with any better keywords. So here's what I need: I'm creating a chat application and on my page, there's a list of online users. When I click on User 1, a div with that user&apo ...

What is the process for duplicating a group containing loaded .obj models?

Initially, I created a new THREE.Object3D() and named it groupChair. I then loaded 3 obj files and added them to groupChair within the callback function. After that, I added the groupChair to the scene and it worked perfectly. However, I encountered an iss ...

Tips for attaching a "progress" and refresh event to an ajax call while sending a file

I am currently using the FormData API and AJAX to upload files to a server in PHP-CodeIgniter. The file upload works perfectly when triggered by the file select event. However, I would like to display a progress bar next to each file being uploaded with th ...

Jest tests are failing to render React IonDateTime component

While executing Jest on an Ionic React component, I encountered a test failure consistently, regardless of whether the component had a time value or not. test('IonDateTime display', () => { render(<IonDatetime data-testid="foo" ...

What is the best way to make my if statement pause until a GET request finishes (GUARD) with the help of Angular?

I am currently working on implementing admin routes for my Angular app, and I have used a role guard to handle this. The code snippet below showcases my implementation: However, I would like the get request to finish executing before the if statement begi ...

What is the best way to retrieve the values from the labels for two separate buttons?

I designed a pair of buttons with a single label below. Both buttons acted as standalone entities. <label for="buttons" class ="val">0</label> <input class="btn btn-primary button1" type="button" ...

angular8StylePreprocessorSettings

I'm currently trying to implement the approach found on this tutorial in order to import scss files through stylePreprocessorOptions in Angular 8. However, I'm encountering an error stating that the file cannot be found. Any suggestions on how to ...

Find the elements of <a> tags specifically without the attribute href

Currently, I am extracting the class of all <a> elements in an HTML document of a webpage using VB.net from a WinForm: Dim htmlLinks As HtmlElementCollection = WebBrowser1.Document.GetElementsByTagName("a") For Each link As HtmlElement In htmlLi ...