创建传递过滤器的连续值流

时间:2017-11-29 00:30:37

标签: functional-programming rxjs reactive-programming reactivex

说我有一个数字流

--- 1 ----- 1 ---- 1 ---- 0 ---- 0 ---- ---- 1 1 ---- 0 --->

我希望得到一个包含连续1的新数组流

--- [1,1,1] --- [1,1] --->

我虽然使用扫描功能,但只发出一个值,我读了一些关于bufferToggle但文档只将它与定时的observable一起使用。有没有这样做的功能?

2 个答案:

答案 0 :(得分:2)

一种可能的方法是将scanpairwise运算符一起使用。

使用成对,您可以将N-1发射与N进行比较。



console.clear();
var source = Rx.Observable.of(1, 1, 1, 0, 0, 1, 1, 0);

source
  .concat(Rx.Observable.of(0)) // for the case when source completes with 1
  .scan(function(acc, x) {
    // reset accumulator to an empty array when a 0 is encountered
    if (x === 0) {
      return [];
    } else {
      return acc.concat([x]);
    }
  }, [])
  .pairwise()
  // filter when the accumulated value goes from a length greater than 0
  // to 0 then you know you've hit 0
  .filter((pair) => pair[0].length > 0 && pair[1].length === 0)
  // take the first element of the pair since it has the result you're interested in
  .map((pair) => pair[0])
  .subscribe(console.log)

<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/5.0.2/Rx.min.js"></script>
&#13;
&#13;
&#13;

答案 1 :(得分:2)

可以将源本身用作bufferToggle的信号 - 它使用observable来控制缓冲区的打开和关闭。

但是,您必须小心订阅源的顺序。特别是,用于发出缓冲区打开和关闭信号的observable必须在bufferToggle observable预订之前订阅

可以使用publishSubject完成此操作,如下所示:

&#13;
&#13;
const source = Rx.Observable.of(1, 1, 1, 0, 0, 1, 1, 0);
const published = source.publish();

const signal = new Rx.Subject();
published.subscribe(signal);

const buffered = published.bufferToggle(
  signal
    .startWith(0)
    .pairwise()
    .filter(([prev, last]) => (prev === 0) && (last === 1)),
  () => signal.filter(value => value === 0)
);

buffered.subscribe(value => console.log(value));
published.connect();
&#13;
.as-console-wrapper { max-height: 100% !important; top: 0; }
&#13;
<script src="https://unpkg.com/rxjs@5/bundles/Rx.min.js"></script>
&#13;
&#13;
&#13;

Subject是必需的,因为每次发出一个值时,都会对用于表示缓冲区关闭的observable进行预订。

我应该补充一点,我提交此答案不是因为我认为它比其他答案更好,而是表明可以使用 buffer (和 window )运算符,其中包含从源派生的信号。必须要小心,这就是全部。使用RxJS,通常不止一种方法可以做某事。

此外,创建re-usable, lettable/pipeable operator以帮助解决这些问题也很容易。