Rx按标准过滤,n标准后过滤

时间:2012-03-03 10:37:50

标签: c# .net linq system.reactive

仅按标准过滤

changes.Where(p => Evaluate(p)).Subscribe(p => { // Do something });

但你怎么能做到这一点,以便在满足标准后获得标准值和n值(并且这些n值不必与评估标准相匹配)?

  • e.g。我想订阅一个在Evaluate(p)上返回的流和一个后面的值(然后再开始评估p

3 个答案:

答案 0 :(得分:4)

请查看SkipWhileTakeIEnumerable扩展方法。您可以尝试以下代码:

changes.SkipWhile(change => Evaluate(change) == false).Take(n).Subscribe(change => { /* do something */ });

修改

使用n项目的尾部从序列中获取所有匹配项目的新代码(不重复检索项目)

// Let's assume elements in the sequence are of type Change
int i = 0;
Func<Change, bool> evaluateWithTail = change =>
{
    if (i <= 0 || i > n)
    {
        i = Evaluate(change) ? 1 : 0;
    }
    else
    {
        i++;
    }

    return i > 0;
}
// Please note delegate is specified as parameter directly - without lambda expression
changes.Where(evaluateWithTail).Subscribe(change => { /* do something */ });

答案 1 :(得分:3)

这是另一个更短的实现:

var filtered = source
  .SkipWhile( x => !Criteria(x) )
  .Take(3)
  .Repeat()

答案 2 :(得分:2)

我认为你不能通过组合现有的运算符来创建一个Rx运算符,因为基本上你想要的是使用Where运算符,但是在它匹配之后你想要为下一个N“关闭它”元素。好的,显然你可以使用Repeat运算符来证明Rx是如何组合的。

无论如何,您还可以使用创建自己的Rx运算符的最佳实践创建一个新运算符:

static class Extensions {

  public static IObservable<T> WhereThenTake<T>(
    this IObservable<T> source,
    Predicate<T> predicate,
    Int32 count
  ) {
    if (source == null)
      throw new ArgumentNullException("source");
    if (predicate == null)
      throw new ArgumentNullException("predicate");
    if (count < 0)
      throw new ArgumentException("count");
    return Observable.Create<T>(
      observer => {
        var finished = false;
        var n = 0;
        var disposable = source.Subscribe(
          x => {
            if (!finished) {
              if (n > 0) {
                observer.OnNext(x);
                n -= 1;
              }
              else if (predicate(x)) {
                n = count;
                observer.OnNext(x);
              }
            }
          },
          ex => { finished = true; observer.OnError(ex); },
          () => { finished = true; observer.OnCompleted(); }
        );
        return disposable;
      }
    );
  }

}

然后您可以像这样使用它(Evaluate是您的谓词,n是谓词匹配后要通过的项目数量):

changes.WhereThenTake(Evaluate, n).Subscribe( ... );