【问题标题】:Group objects in an array using RxJS operators or plain Typescript?使用 RxJS 运算符或普通 Typescript 将数组中的对象分组?
【发布时间】:2019-08-10 12:34:29
【问题描述】:

我正在稍微更新这个问题。假设我们有一堆这样的宠物 (This SO question does):

    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 运算符是否会过度杀伤/降低性能?

【问题讨论】:

    标签: javascript node.js angular typescript rxjs


    【解决方案1】:

    它非常复杂,与 RxJs 无关。在这里查看我的 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;
          }, []);
    };
    

    【讨论】:

    • 有趣 - 将 Observable<Pet[]> 转换为数组并像在另一个 SO post 中那样处理它可能更容易,但我希望 RxJS 有一个更简单的方法使用运算符的糖。
    • 这是一个完整的组,然后对您的要求来说太过分了。
    • 是的,有时最好使用经过验证的方法 :)
    猜你喜欢
    • 2023-03-14
    • 1970-01-01
    • 2018-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-30
    • 1970-01-01
    • 2017-06-21
    相关资源
    最近更新 更多