How to filter duplicate data from http response while displaying in client side?

Viewed 224

How do we filter the dublicate data? I am getting response as follows:

{username:'patrick',userid:'3636363',position:'employee'}
{username:'patrick',userid:'3636363',position:'employee'}
{username:'patrick2',userid:'3636365',position:'manager'}

I am trying to display only

{username:'patrick',userid:'3636363',position:'employee'}
{username:'patrick2',userid:'3636365',position:'manager'}

my component:

    onSubmit(data:string){
    this.http.post(this.Url+'Employee?name='data.name,data).subscribe(res=>{
       this.result=filterDuplicate(Object.values(res));
      });
    function filterDuplicate(users:any):any{
     return users.filter(user,index)=>findIndex((u)=>user.username===u.username)===index);
 }
}

html

<div *ngFor="let item of result |employee:'userId'">
{{item.userid}} {{item.username}}{{item.position}}
</div>

I tried using this.result=Array.from(new Set(res.map(value => value.userid))); but it throw error property 'map' doesnot exist on type 'Object' I have also tried creating pipe

declare var _: any; 

@Pipe({
    name: 'employee',
    pure: false
})
@Injectable()
    export class EmployeePipe implements PipeTransform {
        transform(value: any, args: any): any {

         return _.uniqBy(value, args);
    }
}

While using pipe I am getting Error ReferenceError: _ is not defined Any help will be really appreciated to list the distinct value.
res result:

>0:{username:'patrick',userid:'3636363',position:'employee'}
>1:{username:'patrick',userid:'3636363',position:'employee'}
>2:{username:'patrick2',userid:'3636365',position:'manager'}
2 Answers

Edit: If your res is an object, you might want to convert it to an array first

const users = Object.values(res);

If you have an array of user-objects like this:

const users: User[] = [
    { username: 'patrick', userid: '3636363', position: 'employee' },
    { username: 'patrick', userid: '3636363', position: 'employee' },
    { username: 'patrick2', userid: '3636365', position: 'manager' }
];

You can filter the array to contain only unique users using this function (assuming that each user is identified by a unique username)

function filterDuplicateUsers(users: User[]): User[] {
    return users.filter((user, index) => users.findIndex(
        u => user.username === u.username 
    ) === index);
} 

A similar question has been posted here.

I would expect that something like this would work:

this.http.post(`${this.Url}Employee?name=${data.name}`, data).subscribe(res => {
   this.result = filterDuplicateUser(Object.values(res));
});

Readability in your primary logic flow/methods, invoking isolated code complexity in abstracted methods, helps with troubleshooting, modification and working with others.

This answer is only slightly different to nah0131's. Preference for me would be to use a pipe and that responsibility of the subscription is just to assign the values. Also definitely use the User interface suggested in the other answer - I just kept it simple as per the original question.

I'm not entirely sure which filterDuplicateUsers method is more performant, so you can swop either out with this solution. Both the abstracted methods are immutable, so it could be used with some other context within the same component later.

onSubmit(data:string) {
  this.http.post(this.Url+'Employee?name='data.name,data)
    .pipe(map(this.filterDuplicateUsers))
    .subscribe(res => {
      this.result = res;
  });
}

private filterDuplicateUsers(users: any[]) {
  return users.filter(({ userid: oId }, oIndex) =>
    !users.some(({userid: iId}, iIndex) => oIndex > iIndex && oId === iId)
  );
}
Related