如何使用rxjs对数组中的两个字段进行分组?

时间:2019-06-21 11:15:13

标签: angular typescript rxjs

我有一个包含4个字段的数组,并且必须按两个属性进行分组并汇总(求和)分组数组中的一个字段。

尝试按多个分组不起作用。

下面的代码我试图将数组操纵到期望的列表,但是不确定如何使用RxJs达到下面的期望结果

from(this.dummyData)
        .pipe(
          groupBy(
            function (e) {
                return { category: e.category, manDate: e.manDate };   //is this valid at all?
            },
            function (e) { return e; }), 
            mergeMap(group => zip(of(group.key), group.pipe(toArray())))
        )
        .subscribe( function(result) {
          console.log(result);
        });

现有数组:

[{
        category : "Printer",
        manDate : "02/01/2019",
        amount : 90            
      },
      {
        category : "Printer",
        manDate : "02/01/2019",
        amount : 100            
      },
      {
        category : "Printer",
        manDate : "02/03/2019",
        amount : 90            
      },
      {
        category : "Printer",
        manDate : "02/04/2019",
        amount : 90            
      },
      {
        category : "Scanner",
        manDate : "08/21/2019",
        amount : 8            
      },
      {
        category : "Scanner",
        manDate : "08/21/2019",
        amount : 25            
      },
      {
        category : "Scanner",
        manDate : "08/21/2019",
        amount : 20            
      },
      {
        category : "Scanner",
        manDate : "08/21/2019",
        amount : 10            
      }

    ];

预期:

[{
            category : "Printer",
            subCategory : "A",
            manDate : "02/01/2019",
            amount : 190            
          },{
            category : "Printer",
            subCategory : "A",
            manDate : "02/03/2019",
            amount : 90            
          },{
            category : "Printer",
            subCategory : "A",
            manDate : "02/04/2019",
            amount : 90            
          },{
            category : "Scanner",
            subCategory : "A",
            manDate : "08/21/2019",
            amount : 63            
          }]

我需要任何人的帮助才能达到这个结果。

3 个答案:

答案 0 :(得分:1)

from(dummyData)
  .pipe(
    groupBy(// Group them by category and return the appropriate Arrays
      val => val.category
    ),
    mergeMap(group => {
      return group.pipe(toArray());
    }),
    mergeMap((array) => {// Take each from above array and group each array by manDate
      return from(array).pipe(groupBy(
        val => val.manDate,
        ),
        mergeMap(group => {
          return group.pipe(toArray()); // return the group values as Arrays
        })
      );
    }),
    map((val) => { //For each array returned , calculate the sum and map it to the Object you wanted
      let amount = 0;
      val.map(v => {
        amount = amount + v.amount;
      });
      return {category: val[0].category, manDate: val[0].manDate, amount};
    }),
    toArray() //finally combine all returned objects to an array
  ).subscribe(
    val => console.log(val)
);

我很难缠住它,但这似乎行得通。如果有帮助,别忘了投票,谢谢!

答案 1 :(得分:1)

尝试此方法,看它是否适合您的需求。您不需要将RXjs分组为IMO。可能还有更多方法可以为所需的输出操作输入数组,但这是我相对快速且易于阅读的解决方案。让我知道它如何适合您的情况:)

  transform(array: Array<any>) {
    const newArray = [];
    array.forEach(item => {
      const index = newArray.findIndex(
        i => i.category === item.category && i.manDate === item.manDate
      );
      if (index >= 0) {
        newArray[index].amount += item.amount;
      } else {
        newArray.push(item);
      }
    });
    return newArray;
  }

答案 2 :(得分:0)

我认为我们可以在这里使用reduce。

from(dummyData)
.pipe(
groupBy( val => val.category ), // Group them by category and return the appropriate Arrays
mergeMap(group => { return group.pipe(toArray()); }),
mergeMap((array) => {// Take each from above array and group each array by manDate
  return from(array).pipe( 
    groupBy( val => val.manDate, ),
    mergeMap(group => {
      return group.pipe(toArray()); // return the group values as Arrays
    })
  );
}),
mergeMap((array) => {// Take each from above array and group each array by manDate
  return from(array).pipe( 
    reduce((acc, curr) => ({
        category: curr.category, 
        manDate: curr.manDate,
        amount: curr.amount + acc.amount
    }), { category: '', manDate: '', amount: 0})
  );
}),   
).subscribe(
val => console.log(val));