RxJs groupBy 多條件分組

前言

在Angular或Nest.Js中,使用groupBy分組資料相當方便
但應該是在Nest.Js使用到的機會最多XD

畢竟前端通常都是接到處理完的結果了,只需要渲染頁面就好

作法

比如下列資料,只需以shopId分組

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const array = [
{id: 1, shopId: 'a', category: 'AAA', name: 'Andy', birth: '1990/06/25'},
{id: 2, shopId: 'b', category: 'BBB', name: 'Ben', birth: '1989/01/01'},
{id: 3, shopId: 'a', category: 'AXX', name: 'Amy', birth: '1990/06/01'},
{id: 4, shopId: 'b', category: 'BXX', name: 'Brandon', birth: '1989/05/06'},
{id: 5, shopId: 'a', category: 'AAA', name: 'Anderson', birth: '1991/12/06'},
];

from(array).pipe(
groupBy(val => val.shopId),
mergeMap(group => group.pipe(toArray())
);

// 得到結果如下:
[
[
{id: 1, shopId: 'a', category: 'AAA', name: 'Andy', birth: '1990/06/25'},
{id: 3, shopId: 'a', category: 'AXX', name: 'Amy', birth: '1990/06/01'},
{id: 5, shopId: 'a', category: 'AAA', name: 'Anderson', birth: '1991/12/06'},
],
[
{id: 2, shopId: 'b', category: 'BBB', name: 'Ben', birth: '1989/01/01'},
{id: 4, shopId: 'b', category: 'BXX', name: 'Brandon', birth: '1989/05/06'}
]
]

但若想要多條件,依shopId + category當主鍵來分類
很遺憾不能在groupBy無腦的寫成groupBy(val => {shopId: val.shopId, category: val.category}),

後來在stack overflow(參考資料裡)查到解法

他的寫法摻了不少花括號,猛一看一瞬間還以為要寫的很複雜
但其實就是多一個mergeMap,裡面再做一次groupBy就好了!

以上述範例需求:依shopId + category當主鍵來分類
精簡後如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from(array).pipe(
groupBy(val => val.shopId),
mergeMap(group => group.pipe(toArray()),
mergeMap((_array) =>
from(_array).pipe(
groupBy(val => val.category), // 第2個分組條件
mergeMap(group => group.pipe(toArray())),
)
),
// 後面繼續串接所須的業務邏輯
);

// 得到結果如下:
[
[
{id: 1, shopId: 'a', category: 'AAA', name: 'Andy', birth: '1990/06/25'},
{id: 5, shopId: 'a', category: 'AAA', name: 'Anderson', birth: '1991/12/06'},
],
[
{id: 3, shopId: 'a', category: 'AXX', name: 'Amy', birth: '1990/06/01'},
],
[
{id: 2, shopId: 'b', category: 'BBB', name: 'Ben', birth: '1989/01/01'},
{id: 4, shopId: 'b', category: 'BXX', name: 'Brandon', birth: '1989/05/06'}
]
]

若還有第三、第四個分組條件
依樣畫葫蘆繼續接mergeMap

參考資料

stack overflow / How to groupby by two fields from array using rxjs?