Group data by key with the groupBy operator rxjs

Рейтинг: 0Ответов: 1Опубликовано: 25.08.2023

"rxjs": "7.8.0",

C сервера приходит Observable c таким значением:

[
    {
        "id": 1,
        "date": 1693229400000,
        "name": "event name",
        "impact": "Low",
    },
    {
        "id": 2,
        "date": 1693229400000,
        "name": "event name",
        "impact": "Low",
    },    
    {
        "id": 3,
        "date": 1693229400000,
        "name": "event name",
        "impact": "Middle",
    }
]

Я хочу сгруппировать ответ по полю impact. Но код ниже ничего не возвращает, но и ошибка не падает. console.log не выводится.

events$ = this.onSubmit.pipe(
    switchMap((dateRange) => this.eventService.getEvents())
  ).pipe(
    mergeMap(res => res),
    groupBy(i => i.impact),
    mergeMap(group => group.pipe(toArray())),
  ).subscribe(res => console.log('RESULT', res));

Ответы

▲ 1

Если я правильно понимаю, то в Observable приходят события с массивами объектов, и собственно вы хотите сгруппировать именно объекты этого массива.

groupBy от rxjs группирует именно события в Observable

Подошло если бы вам приходило по одному объекту за событие:

Для примера я сунул ваш массив в from() (что породит события на каждый элемент), данный код должен отработать

from([
    {
        "id": 1,
        "date": 1693229400000,
        "name": "event name",
        "impact": "Low",
    },
    {
        "id": 2,
        "date": 1693229400000,
        "name": "event name",
        "impact": "Low",
    },    
    {
        "id": 3,
        "date": 1693229400000,
        "name": "event name",
        "impact": "Middle",
    }
])
.pipe(
    mergeMap(res => res),
    groupBy(i => i.impact),
    mergeMap(group => group.pipe(toArray())),
  ).subscribe(res => console.log('RESULT', res));

Существует решение для вас https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/groupBy но у него почти нет поддержки, рекомендую воспользоваться Array.reduce()

Пример (грязный):

res.reduce((acc, next) => {
  if (!acc[next.impact]) {
    acc[next.impact] = [];
  }
  acc[next.impact].push(next);
  return acc;
}, {});