如何通过一个值'延迟'可观察序列?

时间:2014-11-27 10:10:08

标签: c# .net system.reactive

在Reactive Extensions中,我怎能延迟'一个值的可观察序列?例如:

original: 2 3 5 7 9   
delayed:    2 3 5 7

要清楚,我想将序列延迟一步。这与延迟一段时间不同。

3 个答案:

答案 0 :(得分:6)

试试这个:

var delayedByOne = source.Zip(source.Skip(1), (x, _) => x);

但是如果你有一个冷可观察源,你可能需要这样做以避免运行两个并发源:

var delayedByOne = source.Publish(s => s.Zip(s.Skip(1), (x, _) => x));

答案 1 :(得分:3)

不需要发布,但它需要在一个方法中获得良好的类型推断,如下所示:

public static class ObservableExtensions
{
    public static IObservable<T> DelayByOne<T>(
        this IObservable<T> source)
    {
        return source.Scan(
            Tuple.Create(default(T), default(T)),
                (a, i) => Tuple.Create(i,a.Item1))
            .Select(a => a.Item2).Skip(1);
    }
}

这个想法源于此http://www.zerobugbuild.com/?p=213#comment-884。你可以看到上面真的是一般比较功能的专业化。从评论到我原来的博客文章,这里是用于比较当前和之前事件的修订实用程序功能:

// The result selector is passed (curr, prev) and
// prev is default(T) for first event
public static class ObservableExtensions
{
    public static IObservable<TResult> CombineWithPrevious<TSource, TResult>(
        this IObservable<TSource> source,
        Func<TSource,TSource,TResult> resultSelector)
    {
        return source.Scan(
            Tuple.Create(default(TSource), default(TSource)),
                (a, i) => Tuple.Create(i,a.Item1))
            .Select(a => resultSelector(a.Item1, a.Item2));
    }
}

所以你可以这样使用上面的内容:

var delayedByOne = source.CombineWithPrevious((x,y) => y).Skip(1);

答案 2 :(得分:3)

刚刚意识到更简洁的方法:

var delayedByOne = source.Publish(ps => ps.Delay(_ => ps));