得到的IObservable前一个元素,而无需重新评估顺序 [英] Get previous element in IObservable without re-evaluating the sequence
问题描述
在的IObservable
序列(在无扩展为.NET),我想获得以前和当前元素的值,这样我可以比较它们。我在网上找到类似下面这完成任务的一个例子:
In an IObservable
sequence (in Reactive Extensions for .NET), I'd like to get the value of the previous and current elements so that I can compare them. I found an example online similar to below which accomplishes the task:
sequence.Zip(sequence.Skip(1), (prev, cur) => new { Previous = prev, Current = cur })
它工作正常,除了它评估序列两次,我想避免的。你可以看到,它正在与此代码两次评估:
It works fine except that it evaluates the sequence twice, which I would like to avoid. You can see that it is being evaluated twice with this code:
var debugSequence = sequence.Do(item => Debug.WriteLine("Retrieved an element from sequence"));
debugSequence.Zip(debugSequence.Skip(1), (prev, cur) => new { Previous = prev, Current = cur }).Subscribe();
输出显示两倍的调试线路,因为有序列中的元素。
The output shows twice as many of the debug lines as there are elements in the sequence.
我明白为什么会这样,但到目前为止,我还没有发现,不计算两次序列的替代品。我怎么可以结合以前和当前只有一个序列的评价?
I understand why this happens, but so far I haven't found an alternative that doesn't evaluate the sequence twice. How can I combine the previous and current with only one sequence evaluation?
推荐答案
有对这个更好的解决方案,我认为,使用Observable.Scan和避免双重订阅:
There's a better solution to this I think, that uses Observable.Scan and avoids the double subscription:
public static IObservable<Tuple<TSource, TSource>>
PairWithPrevious<TSource>(this IObservable<TSource> source)
{
return source.Scan(
Tuple.Create(default(TSource), default(TSource)),
(acc, current) => Tuple.Create(acc.Item2, current));
}
我写这件事在我的博客在这里:的http://www.zerobugbuild.com/?p=213
进一步的修改,您可以使用任意类型的更清洁利用结果选择工作:
A further modification allows you to work with arbitrary types more cleanly by using a result selector:
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)),
(previous, current) => Tuple.Create(previous.Item2, current))
.Select(t => resultSelector(t.Item1, t.Item2));
}
这篇关于得到的IObservable前一个元素,而无需重新评估顺序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!