可观察的<ienumerable>获得序列元素之间的差异

时间:2017-06-20 17:07:06

标签: c# system.reactive

我有一个observable,它发出一系列IEnumerables

1:[1,2,3,4]

2:[1,3,4]

3:[1,5,6]

等。

我想尝试从中创建两个observable:

  • 发出IEnumerable新增元素的一个:

1:[1,2,3,4]

2:[]

3:[5, 6]

等。

  • 发出IEnumerable新删除元素的那个:

1:[]

2:[2]

3:[3,4]

等。

有没有办法使用System.Reactive执行此操作,而无需依赖保持单独的数据结构来比较更改?

2 个答案:

答案 0 :(得分:3)

如果您使用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));
    }
}

这里有一些转轮代码:

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

答案 1 :(得分:0)

如果您希望添加和删除从序列的开头累积,您需要记住以前的内容。

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

}