从Observable中获取每个第N个元素

时间:2017-06-02 19:52:10

标签: c# system.reactive

我需要观察一个以固定间隔生成值的流,但是我想要的值太多了,比如生成每十个值就有一个值。

这样做的等效非RX方式是:

int step = 10;  // take every 10th value
var numbers = Enumerable.Range(0, 100).Where((e, i) => i % step == 0);

在Rx中这样做的惯用方法是什么?

2 个答案:

答案 0 :(得分:2)

我会使用WhereBuffer

int step = 10;  // take every 10th value

// Where
var numbers = Observable.Range(0, 100).Where((e, i) => i % step == 0);

// Buffer
numbers = Observable.Range(0, 100).Buffer(step).Select(x => x[step - 1]);

答案 1 :(得分:1)

我会避免使用带有 Where 参数的 Func<TSource, int, bool> predicate 运算符,因为担心可能出现 OverflowException。如果源序列产生超过 2,147,483,647 个元素,就会发生这种情况。 Linq 和 Rx 运算符都允许发生算术溢出,我不知道有什么解决方法可以防止这种情况发生。

以下是在这方面安全的自定义 TakeEvery 运算符:

/// <summary>Samples the observable sequence by returning one every N elements,
/// ignoring the other elements.</summary>
public static IObservable<T> TakeEvery<T>(this IObservable<T> source, int step)
{
    if (step < 1) throw new ArgumentOutOfRangeException(nameof(step));
    return Observable.Defer(() =>
    {
        int index = -1;
        return source.Where(value => (index = ++index % step) == 0);
    });
}