0

I have already consulted other questions regarding this issue but I have not pulled a spider out of the hole. I have to use distinct on an array of objects, with the code that I propose to you the distinct does not work and I have no errors in the console. How can I make it work?

carRecent

export class CarRecent {

    id:number;
    carId:number;
    userId:number;
    imageURL:string;

}

carsService

 getRecentCars(userId){

    let params = new HttpParams().set('userId', userId);
    let options = {headers:this.headers, params:params};

    return this.http.get<CarRecent[]>(this.host + 'getRecentCars', options);

  }

recentCar.component.ts

export class RecentCarsComponent implements OnInit {

  url:string = 'assets/';

  recentCars = new BehaviorSubject<CarRecent[]>(null);
  subscriptionRecentCars;

  constructor( public carsService:CarsService, public authService:AuthenticationService ) { }

  ngOnInit(): void {

    this.loadRecentCars();

  }

  loadRecentCars(){

    this.subscriptionRecentCars = this.carsService.getRecentCars(this.authService.currentUserValue.id)
    .pipe( 
      tap( cars => console.log(cars) ),
      distinct( (car:any) => car.carId )
    )  
    .subscribe({
        next:cars => {
          this.recentCars.next(cars);
        }
      })

  }

}

1 Answer 1

3

RxJS operators are often confused with array functions, but they operate on the whole value returned by the observable - they aren't specific to arrays.

In your case you want to return a distinct array of objects based on some key. You want to transform the array returned by the observable to another value - a subset of the array. When transforming data in the pipe, use the map operator.

Once you're inside the map operator, you can reduce the array to return distinct values.

ngOnInit() {

  this.carsService.getRecentCars(this.authService.currentUserValue.id)
    .pipe( 
      tap(cars => console.log(cars)),
      map(cars => {
        const uniques = new Set();
        return cars.reduce((arr, current) => {  
          if (!uniques.has(current.carId)) {
            arr.push(current);
            uniques.add(current.carId);
          }
          return arr;
        }, []);
      })
    ).subscribe({ 
      next:cars => {
        this.recentCars.next(cars);
      }
    });  
}

I have used a Set to avoid redundant array iterations.

DEMO: https://stackblitz.com/edit/angular-8qnsp8

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.