在rxjs中,如何创建顺序值组?

时间:2019-06-13 15:05:25

标签: rxjs reactive-streams

我有这种形式的值流:

[1,2,3,1,2,1,1,1,2...]

我想将其转换为以下形式的组流:

[[1,2,3],[1,2],[1],[1],[1,2]...]

每当值变为1时应创建一个新组。

2 个答案:

答案 0 :(得分:3)

您可以使用bufferWhen()运算符来收集发出的值,直到可观察对象发出值为止。在此示例中,我使用一个主题将流的浅表副本发送到缓冲区。

每次发出数字1时,缓冲区就会发出。如果流以1开头,则会发出一个空数组。所以我过滤掉了。

const {from, Subject} = rxjs;
const {filter, bufferWhen, tap, skip} = rxjs.operators;

const stream = from([1,2,3,1,2,1,1,1,2]);
const trigger = new Subject();

stream.pipe(
   tap(v => trigger.next(v)),
   bufferWhen(() => trigger.pipe(filter(v => v === 1))),
   filter(v => v.length)
).subscribe(x => console.log(x));
<script src="https://unpkg.com/@reactivex/rxjs@6.x/dist/global/rxjs.umd.js"></script>

如果要在值减小时触发该触发器,则可以使用scan()。在逻辑上可能会更好一些,但是使用1作为触发条件可以解决问题。

答案 1 :(得分:0)

为便于记录,我发布了一个替代已接受答案的解决方案。

注意:对于有限的流,在concat(of(1))之前需要scan(),以便distinctUntilChanged发出最后一个可观察到的信号。

const {of, from, ReplaySubject} = rxjs;
const {map, concat, scan, distinctUntilChanged, concatAll, toArray, delay} = rxjs.operators;

//considering infinite stream
const stream = from([1,2,3,1,2,1,1,1,2]);
stream.pipe(
    scan( (acc, val) => {
        if(val===1){
            acc.complete()
            acc=new ReplaySubject();
        }
        acc.next(val);
        return acc;
    }, new ReplaySubject()), 
    distinctUntilChanged(), 
    map(toArray()), 
    concatAll() );

很高兴收集有关首选解决方案的反馈。