代码之家  ›  专栏  ›  技术社区  ›  Reza

如果在rxjs中没有连续重复3次,如何跳过0值

  •  0
  • Reza  · 技术社区  · 4 年前

    1 > 4 > 0 > 3 > 1 > 0 > 0 > 0 > 1 > 2 > 0 > 0 > 0 > 0 > 0 > 0

    我想要 0 仅当它连续重复3次或更多次时才会发出,因此预期结果如下

    1 > 4 > 3 > 1 > 0 > 1 > 2 > 0

    在rxjs中如何实现这一点?

    0 回复  |  直到 4 年前
        1
  •  3
  •   Rafi Henig    4 年前

    您可能希望按照以下示例实现它:

    const { from } = rxjs;
    const { scan, filter, map} = rxjs.operators;
    
    
    const input = [
        1, 4, 0, 3, 1, 0, 0, 0, 
        1, 2, 0, 0, 0, 0, 0, 0,
        2, 0, 2, 4, 0, 0, 3, 9,
        4, 3, 0, 0, 0, 0, 0, 0,
    ];
    
    from(input).pipe(
        scan(({ counter }, current) => {
    
            if (current === 0) return { current, counter: ++counter, emit: counter == 3 }
            else return { current, counter: 0, emit: true };
    
        }, { emit: false, counter: 0, current: undefined }),
    
        filter(x => x.emit), 
    
        map(x => x.current) 
    )
    .subscribe(console.log)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.6.2/rxjs.umd.min.js"></script>
        2
  •  2
  •   Guilhermevrs    4 年前

    实际上,您可以使用scan/filter/map。

    const {
      Observable,
      from
    } = rxjs;
    
    function groupRepeatedNumbers(opts = {
      minLimit: 3,
      desiredNumber: 0
    }) {
      return function(source) {
        let numberCounter = 0;
        return new Observable(subscriber => {
          source.subscribe({
            next(value) {
              if (value !== opts.desiredNumber) {
                numberCounter = 0;
                subscriber.next(value);
              } else if (++numberCounter === opts.minLimit) {
                subscriber.next(value);
              }
            },
            error(error) {
              subscriber.error(error);
            },
            complete() {
              subscriber.complete();
            }
          })
        });
      }
    }
    
    const input = [
      1, 4, 0, 3, 1, 0, 0, 0,
      1, 2, 0, 0, 0, 0, 0, 0,
      2, 0, 2, 4, 0, 0, 3, 9,
      4, 3, 0, 0, 0, 0, 0, 0,
    ];
    
    from(input).pipe(
        groupRepeatedNumbers()
      )
      .subscribe(console.log)
    <script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/6.6.2/rxjs.umd.min.js"></script>

    您可以看到,您甚至可以将操作员配置为按需操作,如:

    groupRepeatedNumbers({
      minLimit: 5,
      desiredNumber: 3
    }) // Will group the number 3, and only emit when it gets 5 or more occasions
    
        3
  •  1
  •   frido    4 年前

    defer 跟踪自定义运算符中的变量(如计数器),同时为每个订户提供自己的新变量(如果您有多个订户,这一点很重要)。

    import { defer, MonoTypeOperatorFunction, Observable } from 'rxjs'; 
    import { filter } from 'rxjs/operators';
    
    function sequentialLimit<T>(
      condition: (value: T) => boolean, 
      limit: number
    ): MonoTypeOperatorFunction<T> {
      return (source: Observable<T>) => defer(() => {
        let counter = 0;
        return source.pipe(
          filter(v => {
            condition(v) ? counter++ : counter = 0;
            return counter === 0 || counter === limit;
          })
        );
      });
    }
    

    用法:

    const input = [
      1, 4, 0, 3, 1, 0, 0, 0, 1, 2, 0, 0, 0, 0, 0, 0,
      2, 0, 2, 4, 0, 0, 3, 9, 4, 3, 0, 0, 0, 0, 0, 0,
    ];
    
    from(input).pipe(
      sequentialLimit(v => v === 0, 3)
    ).subscribe(console.log)
    

    https://stackblitz.com/edit/rxjs-zpwnxq?file=index.ts