Группировать объекты в массив, используя операторы RxJS или обычный Typescript? - PullRequest
0 голосов
/ 20 марта 2019

Я немного обновляю этот вопрос. Предположим, у нас есть такие домашние питомцы ( Этот ТАК вопрос ):

    const pets = [
        {type:"Dog", name:"Spot"},
        {type:"Cat", name:"Tiger"},
        {type:"Dog", name:"Rover"}, 
        {type:"Cat", name:"Leo"}
    ];

Мы получаем их как Observable<Pet[]>. Мы бы подписались и использовали группу, описанную в справочном вопросе, чтобы классифицировать домашних животных по типу. Другими словами:

petsObservable.subscribe(petsArray=>...categorize them using plain javascript)

const groupedPets = groupBy(pets, pet => pet.type);

Однако мне любопытно, существует ли более короткий и элегантный подход к этому с использованием операторов RxJS для получения прямого результата, на который мы можем подписаться? Что-то вроде:

 petObservable.pipe(...apply operators).subscribe( map=>)

Также любопытно, будет ли использование операторов RxJS превышать / понижать производительность в соответствии с обсуждением в первом ответе?

1 Ответ

1 голос
/ 20 марта 2019

Он довольно сложный и не имеет ничего общего с RxJ.Смотрите мой StackBlitz здесь.

https://stackblitz.com/edit/typescript-ezydzv?file=index.ts

export interface Group {
  key: any;
  items: any[];
  sum?: any;
}

export interface GroupBy {
  keys: string[];
  sum?: string[];
  thenby?: GroupBy;
}

export const resolveProperty = (obj: any, property: string): any =>
  property.split('.').reduce((result, prop) => (result ? result[prop] : undefined), obj);

export const sumGroup = (group: Group, sum: string[]): Group => {
  if (!sum || !sum.length || !group) {
    return group;
  }
  return {
    ...group,
    sum: sum.reduce(
      (sumObj, sumProp) => ({
        ...sumObj,
        [sumProp]: group.items.reduce((a, b) => resolveProperty(a, sumProp) + resolveProperty(b, sumProp))
      }),
      {}
    )
  };
};

export const groupBy = (array: any[], grouping: GroupBy): Group[] => {
  if (!array) {
    return array;
  }
  const keys = grouping.keys;
  const groups: Group[] = array.reduce((results: Group[], item) => {
    const group = results.find(g => keys.every(key => item[key] === g.key[key]));
    const data = Object.getOwnPropertyNames(item).reduce((o, prop) => {
      if (!keys.some(key => key === prop)) {
        o[prop] = item[prop];
      }
      return o;
    }, {});
    if (group) {
      group.items.push(data);
    } else {
      results.push({
        key: keys.reduce((o, key) => {
          o[key] = item[key];
          return o;
        }, {}),
        items: [data]
      });
    }
    return results;
  }, []);
  return grouping.thenby
    ? groups.map(g => ({ ...g, items: groupBy(g.items, grouping.thenby) }))
    : groups.reduce((arr, g) => {
        arr.push(sumGroup(g, grouping.sum));
        return arr;
      }, []);
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...