说我有一个数字流
--- 1 ----- 1 ---- 1 ---- 0 ---- 0 ---- ---- 1 1 ---- 0 --->
我希望得到一个包含连续1的新数组流
--- [1,1,1] --- [1,1] --->
我虽然使用扫描功能,但只发出一个值,我读了一些关于bufferToggle但文档只将它与定时的observable一起使用。有没有这样做的功能?
答案 0 :(得分:2)
一种可能的方法是将scan
与pairwise
运算符一起使用。
使用成对,您可以将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;
答案 1 :(得分:2)
可以将源本身用作bufferToggle
的信号 - 它使用observable来控制缓冲区的打开和关闭。
但是,您必须小心订阅源的顺序。特别是,用于发出缓冲区打开和关闭信号的observable必须在bufferToggle
observable预订之前订阅。
可以使用publish
和Subject
完成此操作,如下所示:
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;
Subject
是必需的,因为每次发出一个值时,都会对用于表示缓冲区关闭的observable进行预订。
我应该补充一点,我提交此答案不是因为我认为它比其他答案更好,而是表明可以使用 buffer
(和 window
)运算符,其中包含从源派生的信号。必须要小心,这就是全部。使用RxJS,通常不止一种方法可以做某事。
此外,创建re-usable, lettable/pipeable operator以帮助解决这些问题也很容易。