Search code examples
angularrxjsobservablejavascript-objectsrxjs-observables

GroupBy or Reduce on Array of Objects Observable


I'm using Angular 14.

I have an Observable that is an Array of Objects, looks like a dictionary with key/values.

Array: [
  0: Object {id: 100, manufacturer: 'ford', model: 'mustang'},
  1: Object {id: 110, manufacturer: 'ford', model: 'fiesta'},
  2: Object {id: 150, manufacturer: 'ford', model: 'escort'},
  3: Object {id: 320, manufacturer: 'Toyota', model: 'camry'},
  4: Object {id: 325, manufacturer: 'Toyota', model: 'rav4'},
  5: Object {id: 345, manufacturer: 'Toyota', model: 'corolla'},

]

I want to group this array by manufacturer. I need two separate lists for Ford and Toyota.

I have read about the RxJs .groupBy() but I can't get it to work as this is a dictionary.

this.cars$.pipe(
        groupBy(g => g[??????].manufacturer),
        mergeMap(group => group.pipe(toArray()))
      ).subscribe(s => { .... });

I have also read about the Javascript reduce() function but it is difficult to understand and I can't find an example of it reducing a dictionary.

Any help appreciated!


Solution

  • To group your array of objects by manufacturer, you can use the reduce() method to create a new object with keys for each manufacturer and values as arrays of cars.

    Here's an example implementation:

    this.cars$.pipe(
      map(cars => cars.reduce((acc, car) => {
        if (!acc[car.manufacturer]) {
          acc[car.manufacturer] = [];
        }
        acc[car.manufacturer].push(car);
        return acc;
      }, {})),
    ).subscribe(manufacturers => {
      const fordCars = manufacturers['ford'];
      const toyotaCars = manufacturers['Toyota'];
      // Do something with the grouped arrays
    });
    

    Explanation:

    • map() operator is used to transform the original Observable of cars array into a new Observable that emits an object with manufacturers as keys and arrays of cars as values.
    • reduce() method is used to iterate through each car in the array and add it to the corresponding manufacturer array in the accumulator object.
    • The accumulator object starts as an empty object {}.
    • If the manufacturer array doesn't exist yet, it's initialized with an empty array.
    • The acc (accumulator) object is returned at the end of each iteration, which builds up the final grouped object.
    • The subscribe() method is used to consume the resulting object and extract the arrays for Ford and Toyota, which can be used for further processing.

    Hope this helps!