0

In this mat-option i'm tryng to show data from an observable i subscribed to.

   <mat-option *ngFor="let option of (filteredCustomer | async)?.Items"
   [value]="option" (onSelectionChange)="searchDest($event)">
   {{option.Cityname}} 
   </mat-option>

The name of the observable is filteredCustomer.

Now in the mat option i'm tryng to show city names. Thats the result.

Los Angeles
Boston
Detroit
Los Angeles
Washington
Los Angeles

As you can see i have duplicates.

It's possible to remove duplicates (like a distinct in sql)?

My observable come from this ts file:

public filterCity() {
 var parameters = new CitySearchParameters(100, 0);
 parameters.City = this.city;    
 this.filteredCustomer = this.customerService.get(parameters);
 if (typeof (this.city) == "object") {
  var curCity: any = this.city;
  this.city = curCity.City;
 }
}

Thanks

Daniel Widdis
  • 8,424
  • 13
  • 41
  • 63

3 Answers3

0

The Set object lets you store unique values of any type, whether primitive values or object references.

So you can convert the list the duplicates will be removed.

    let list = [...new Set(this.filteredCustomer)];

another approach to use filter

let chars = ['A', 'B', 'A', 'C', 'B'];

let uniqueChars = chars.filter((c, index) => {
    return chars.indexOf(c) === index;
});

console.log(uniqueChars); // results = [ 'A', 'B', 'C' ]

yazan
  • 518
  • 3
  • 16
  • with Set method i have this error: No overload matches this call. Overload 1 of 2, '(iterable?: Iterable): Set', gave the following error. Argument of type 'Observable' is not assignable to parameter of type 'Iterable'. Property '[Symbol.iterator]' is missing in type 'Observable' but required in type 'Iterable'. Overload 2 of 2, '(values?: readonly any[]): Set', gave the following error. Argument of type 'Observable' is not assignable to parameter of type 'readonly any[]'. – federico.bessi Nov 16 '20 at 10:13
  • https://wsvincent.com/javascript-remove-duplicates-array/#:~:text=The%20simplest%20approach%20(in%20my,automatically%20remove%20duplicates%20for%20us.&text=Another%20option%20is%20to%20use%20filter().&text=And%20finally%20we%20can%20use%20forEach()%20. – yazan Nov 16 '20 at 10:34
0

You could use the RxJS reduce operator to keep your async pipe working, something like this, assuming that you are removing duplicates based on .Cityname property

public filterCity() {
  var parameters = new CitySearchParameters(100, 0);
  parameters.City = this.city;
  this.filteredCustomer = this.customerService.get(parameters).pipe(
    reduce((list, val) => {
      if (!list.length) return [val]
      const foundIndex = list.findIndex((item) => item.cityname === val.cityname);
      if (foundIndex === -1) {
        list.push(val);
      }

      return list;
    }, [])
  );
  if (typeof(this.city) == "object") {
    var curCity: any = this.city;
    this.city = curCity.City;
  }
}
CapitanFindus
  • 1,498
  • 15
  • 26
0

You could use Array#filter with Array#findIndex to remove duplicates in an array.

// credit: https://stackoverflow.com/a/36744732/6513921
private uniqueArray(target: Array<any>, property: any): Array<any> {
  return target.filter((item, index) =>
    index === target.findIndex(t => 
      t[property] === item[property]
    )
  );
}

You could then "capture" the emission from the observable in the controller using map operator and remove the duplicates before rendering them in the template

public filterCity() {
  var parameters = new CitySearchParameters(100, 0);
  parameters.City = this.city;
  this.filteredCustomer = this.customerService.get(parameters).pipe(
    map(customer => ({
      ...customer,
      Items: uniqueArray(customer.Items, 'Cityname')  // <-- remove duplicates by `Cityname` property
    }))
  );
  if (typeof (this.city) == "object") {
    var curCity: any = this.city;
    this.city = curCity.City;
  }
}

The spread operator ... is used to retain other properties in the emission from the observable except the Items property array. It is modified to remove the duplicates.

ruth
  • 29,535
  • 4
  • 30
  • 57
  • It works fine. In this way i have a dedicated method (the one you called uniqueArray) that will be useful in future. Thanks a lot. – federico.bessi Nov 16 '20 at 11:41