简体   繁体   English

可观察 <IEnumerable> 得到序列元素之间的差异

[英]Observable<IEnumerable> get differences between sequence elements

I have an observable that emits a sequence of IEnumerables 我有一个可观察到的IEnumerables序列

1: [1,2,3,4] 1: [1,2,3,4]

2: [1,3,4] 2: [1,3,4]

3: [1,5,6] 3: [1,5,6]

etc.. 等等..

I want to try and create two observables from this: 我想尝试从这里创建两个observable:

  • One that emits an IEnumerable of newly added elements: 发出IEnumerable新增元素的一个:

1: [1,2,3,4] 1: [1,2,3,4]

2: [] 2: []

3: [5, 6] 3: [5, 6]

etc.. 等等..

  • One that emits an IEnumerable of newly removed elements: 发出IEnumerable新删除元素的一个:

1: [] 1: []

2: [2] 2: [2]

3: [3,4] 3: [3,4]

etc.. 等等..

Is there a way to do this using System.Reactive without having to rely on keeping a separate data structure to compare changes against? 有没有办法使用System.Reactive执行此操作,而不必依赖于保持单独的数据结构来比较更改?

It's fairly simple if you use Observable.Zip and Enumerable.Except to easily compare element n to element n-1. 如果你使用Observable.ZipEnumerable.Except ,它很容易将元素n与元素n-1进行比较。

public static class IObservableIEnumerableExtensions
{
    public static IObservable<IEnumerable<T>> GetAddedElements<T>(this IObservable<IEnumerable<T>> source)
    {
        return source.Zip(source.StartWith(Enumerable.Empty<T>()), (newer, older) => newer.Except(older));
    }

    public static IObservable<IEnumerable<T>> GetRemovedElements<T>(this IObservable<IEnumerable<T>> source)
    {
        return source.Zip(source.StartWith(Enumerable.Empty<T>()), (newer, older) => older.Except(newer));
    }
}

And here's some runner code: 这里有一些转轮代码:

var source = new Subject<IEnumerable<int>>();

var addedElements = source.GetAddedElements();
var removedElements = source.GetRemovedElements();

addedElements.Dump();   //Using Linqpad
removedElements.Dump(); //Using Linqpad

source.OnNext(new int[] { 1, 2, 3, 4 });
source.OnNext(new int[] { 1, 3, 4 });
source.OnNext(new int[] { 1, 5, 6 });

If you expect adds and removes to be cumulative from the start of the sequence, you need something to remember what has come before. 如果您希望添加和删除从序列的开头累积,您需要记住以前的内容。

public static IObservable<IEnumerable<T>> CumulativeAdded<T>(this IObservable<IEnumerable<T>> src) {
    var memadd = new HashSet<T>();

    return src.Select(x => x.Where(n => memadd.Add(n)));
}

public static IObservable<IEnumerable<T>> CumulativeRemoved<T>(this IObservable<IEnumerable<T>> src) {
    var memdiff = new HashSet<T>();

    return src.Select(x => { foreach (var n in x) memdiff.Add(n); return memdiff.AsEnumerable().Except(x); });
}

} }

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

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