RxJS 数学/聚合类型 Operators (1) - min / max / count / reduce

今天要介绍「数学/聚合类型」的 operators,这些 operators 会把来源 Observable 当作一个单纯的资料列,取得一些基本的资讯,也可以自订如何判断资讯;这些 operators 都非常直觉好懂,就让我们轻松来学习吧!

min

min 会判断来源 Observable 资料的最小值,在来源 Observable 结束後,将最小值事件资料发生在新的 Observable 上。

of(5, 1, 9, 8)
  .pipe(min())
  .subscribe(data => {
    console.log(`min 示范 (1): ${data}`);
  });
// min 示范 (1): 1

弹珠图:

(   5   1   9   8|)
max()
(               1|)

min 内也可以传入 comparer callback function,会传入 xy 代表两个来源 Observable 的事件资料, min 会透过 comparer function 的回传值判断两组资料的大小,这个 callback function 需要回传一个数值,大於 0 代表 x 大於 y,小於 0 代表 x 小於 y,等於 0 代表 xy 相同。

of(
  { name: 'Student A', score: 80 },
  { name: 'Student B', score: 90 },
  { name: 'Student C', score: 60 },
  { name: 'Student D', score: 70 },
).pipe(
  min((studentA, studentB) => studentA.score - studentB.score)
).subscribe(student => {
  console.log(`min 示范 (2): ${student.name} - ${student.score}`);
});
// min 示范 (2): Student C - 60

透过 comparer function,就不用担心传入资料为物件时无法比较罗。

程序码:https://stackblitz.com/edit/mastering-rxjs-operator-min

max

max 刚好跟 min 相反,max 会判断来源 Observable 资料的最大值,在来源 Observable 结束後,将最大值事件资料发生在新的 Observable 上。

of(5, 1, 9, 8)
  .pipe(max())
  .subscribe(data => {
    console.log(`max 示范 (1): ${data}`);
  });
// max 示范 (1): 9

弹珠图:

(   5   1   9   8|)
max()
(               9|)

一样的 max 也可以传入 comparer callback function 来自定判断资料大小比较条件:

of(
  { name: 'Student A', score: 80 },
  { name: 'Student B', score: 90 },
  { name: 'Student C', score: 60 },
  { name: 'Student D', score: 70 },
).pipe(
  max((studentA, studentB) => studentA.score - studentB.score)
).subscribe(student => {
  console.log(`max 示范 (2): ${student.name} - ${student.score}`);
});
// max 示范 (2): Student B - 90

程序码:https://stackblitz.com/edit/mastering-rxjs-operator-max

count

count 可以用来计算来源 Observable 发生过多少次事件:

of(5, 1, 9, 8)
  .pipe(count())
  .subscribe(data => {
    console.log(`count 示范 (1): ${data}`);
  });
// count 示范 (1): 4

上述程序码 of(5, 1, 9, 8) 总共会发生 4 次事件,因此在来源 Observable 结束时,新的 Observable 会得到资料 4 的事件值。

弹珠图:

(   5   1   9   8|)
count()
(               4|)
                ^ 来源 Observable 发生过 4 次事件

count 可以传入 predicate callback function,来判断事件资料是否符合固定条件,当来源 Observable 结束时,新的 Observable 会发生的事件值为「所有符合指定条件事件」的总数:

of(5, 1, 9, 8)
  .pipe(count(data => data > 5))
  .subscribe(data => {
    console.log(`count 示范 (2): ${data}`);
  });
// count 示范 (2): 2

弹珠图:

(   5   1   9   8|)
count(data => data > 5)
(               2|)
                ^ 来源 Observable 符合条件的事件发生过 2 次

程序码:https://stackblitz.com/edit/mastering-rxjs-operator-count

reduce

reduce 用来运算来源 Observable 汇总後的结果,与之前介绍过的 scan 非常像,差别在於 scan 在来源 Observable 发生事件後都会进行运算并同时在新的 Observable 上发生,而 reduce 在来源 Observable 发生事件後,只会进行运算,但不会在新的 Observable 上发生事件,直到来源 Observable 结束时,才在新的 Observable 上发生运算後的结果作为事件。

回顾一下 scan

const donateAmount = [100, 500, 300, 250];

const accumDonate$ = of(...donateAmount).pipe(
  scan(
    (acc, value) => acc + value, // 累加函数
    0 // 初始值
  )
);

accumDonate$.subscribe(amount => {
  console.log(`目前 donate 金额累计:${amount}`)
});
// 目前 donate 金额累计:100
// 目前 donate 金额累计:600
// 目前 donate 金额累计:900
// 目前 donate 金额累计:1150

弹珠图:

(100      500      300      250|)
scan((acc, value) => acc + value, 0)
(100      600      900     1150|)

同样的程序码,我们直接把 scan 换成 reduce

const donateAmount = [100, 500, 300, 250];

const accumDonate$ = of(...donateAmount).pipe(
  reduce(
    (acc, value) => acc + value, // 累加函数
    0 // 初始值
  )
);

accumDonate$.subscribe(amount => {
  console.log(`目前 donate 金额累计:${amount}`)
});
// 目前 donate 金额累计:1150

弹珠图:

(100      500      300      250|)
reduce((acc, value) => acc + value, 0)
(                          1150|)

是不是一下就看出差异啦!

程序码:https://stackblitz.com/edit/mastering-rxjs-operator-reduce

本日小结

  • min:找出来源 Observable 事件的最小值。
  • max:找出来源 Observable 事件的最大值。
  • count:找出来源 Observable 事件总数。
  • reduce:依照指定运算逻辑,找出来源 Observable 事件汇总的结果。

相关资源


<<:  [Android Studio菜鸟的学习分享]我不是机器人-Google reCAPTCHA

>>:  【Day30】综合练习:台铁即时时刻表!

[Day04] Tableau 轻松学 - Tableau 三大软件

前言 Tableau 是多个软件的通称,我们初学在进行 BI 分析时,最常会用到其中的三种,分别为 ...

【Day24-序列】时间序列型资料的基本处理——以0050股票价格为例:寻找峰值、移动平均、曲线拟合

前面我们虽然有讲到除了基本的数值类型资料以外,一共主要会有文字、图片、声音这三大类型,而在数值类型的...

【心得】你今天种菜了吗? grid之路-grid的使用(5)

前言 既然可以使用grid-area为每个区域命名,并填入grid-template-areas中,...

DNS 安全扩展 (DNSSEC)

-DNSSEC 资源记录(来源:InfoBlox) DNSSEC使用数字签名确保DNS 数据的完整...

python os.walk鬼打墙

os.walk 找子目录下特定类型档案,鬼打墙好几天。也写了一两篇po上来,就当是"叠床架...