我需要观察一个以固定间隔生成值的流,但是我想要的值太多了,比如生成每十个值就有一个值。
这样做的等效非RX方式是:
int step = 10; // take every 10th value
var numbers = Enumerable.Range(0, 100).Where((e, i) => i % step == 0);
在Rx中这样做的惯用方法是什么?
答案 0 :(得分:2)
我会使用Where
或Buffer
:
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);
});
}