繁体   English   中英

如何将可观察序列“延迟”一个值?

[英]How to 'delay' observable sequence by one value?

在Reactive Extensions中,如何将可观察序列“延迟”一个值? 例如:

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

需要明确的是,我想将序列延迟一步。 这与延迟固定时间不同。

尝试这个:

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

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

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

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

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);

刚意识到有一种更整洁的较短方法:

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM