C# 如何在移动中生成IObservable索引增量?
我有两个数据源。C# 如何在移动中生成IObservable索引增量?,c#,linq,system.reactive,set-difference,C#,Linq,System.reactive,Set Difference,我有两个数据源。 其中一个是缓存列表,另一个是通过IObservable推送的新数据 我想使用Rx找出需要对缓存列表A执行哪些操作,以使其顺序和内容与新数据相同 我正在寻找一个函数,它接受IEnumerable a和IObservable b,并返回一个可观察的在a上推送操作(插入和删除),使其与b相同,而无需等待b完成。 注意:我知道我不能修改列表或可观察。我不想 我只想知道,一旦这些操作被知道,什么样的操作,以什么样的顺序将把一个在顺序和顺序上与a相同的假设列表变成一个在顺序和顺序上与B相同
其中一个是缓存列表,另一个是通过
IObservable
推送的新数据
我想使用Rx找出需要对缓存列表A执行哪些操作,以使其顺序和内容与新数据相同
我正在寻找一个函数,它接受IEnumerable a
和IObservable b
,并返回一个可观察的在a
上推送操作(插入和删除),使其与b
相同,而无需等待b
完成。
注意:我知道我不能修改列表或可观察。我不想
我只想知道,一旦这些操作被知道,什么样的操作,以什么样的顺序将把一个在顺序和顺序上与a相同的假设列表变成一个在顺序和顺序上与B相同的列表
a
和b
都是唯一的,并且是经过排序的,T
实现了i可比较的
和i可比较的
目标是找到一系列将a转换为B的删除/插入操作。想想a是缓存数据源,B是新数据,我想知道如何在不重新加载的情况下将这些更新转换为网格。
在两个源中对行进行排序
我希望输出是形式的
[(0, true), (1, true), (0, false), (3, false), (4, true), (5, true)]
稍后,我将按布尔标志对这些操作进行分组:
deleted: [0, 3]
inserted: [0, 1, 4, 5]
这可以翻译成人类语言
i可满足的
i可比较的进行降序排序
Current
、MoveNext
、wait
和yield push
语义,但这个想法应该有一定的意义
IObservable<Tuple<int, bool>> IndexDelta(a, b)
{
var indexA = 0;
var indexB = 0;
while (true) {
var headA = a.Current;
var headB = b.Current;
if (headA == null && headB == null) {
return yield break; // both sequences are over
}
var reportDeletion = () => {
yield push Tuple.Create(indexA, false);
await a.MoveNext(); // this one is fast
}
var reportInsertion = () => {
yield push Tuple.Create(indexB, true);
await b.MoveNext(); // can take a long time
}
if (headA == null) { // No source item at this position
reportInsertion();
continue;
}
if (headB == null) { // No fetched item at this position
reportDeletion();
continue;
}
switch (headB.CompareTo(headA)) {
case 0:
yield continue;
break;
case 1: // Fetched item is newer than source item
reportInsertion();
break;
case -1: // Source item is newer than fetched item
reportDeletion();
break;
}
indexA++;
indexB++;
}
}
IObservable IndexDelta(a,b)
{
var indexA=0;
var-indexB=0;
while(true){
var headA=a.电流;
var headB=b.电流;
if(headA==null&&headB==null){
return yield break;//两个序列都结束了
}
var reportDeletion=()=>{
产生push Tuple.Create(indexA,false);
等待a.MoveNext();//这个很快
}
var reportInsertion=()=>{
产生push Tuple.Create(indexB,true);
等待b.MoveNext();//可能需要很长时间
}
如果(headA==null){//此位置没有源项
reportInsertion();
继续;
}
如果(headB==null){//此位置没有获取的项
报告删除();
继续;
}
开关(头B.比较器至(头A)){
案例0:
产量继续增长;
打破
案例1://获取的项比源项新
reportInsertion();
打破
案例-1://源项比获取的项新
报告删除();
打破
}
indexA++;
indexB++;
}
}
我相信您可以实现与主题
非常类似的功能。但是,我不想继续使用这个解决方案,因为我想知道是否有可能纯粹通过组合Rx函数来解决它,例如Aggregate
、Zip
或combinelateest
你的想法是什么?似乎有效
void Main()
{
var a = new int?[] {150, 100, 70, 30, 20 };
var b = new int?[] {300, 200, 100, 70, 60, 50, 20 };
var result = IndexDelta(a, b);
result.Dump();
}
// Define other methods and classes here
IObservable<Tuple<int, bool>> IndexDelta(IEnumerable<int?> a, IEnumerable<int?> b)
{
var observable = Observable.Create<Tuple<int, bool>>(o => {
var indexA = 0;
var indexB = 0;
var aEnumerator = a.GetEnumerator();
var bEnumerator = b.GetEnumerator();
var aHasNext = aEnumerator.MoveNext();
var bHasNext = bEnumerator.MoveNext();
while(true) {
if (aHasNext == false && bHasNext == false) {
"Completed".Dump();
o.OnCompleted(); // both sequences are over
break;
}
var headA = aEnumerator.Current;
var headB = bEnumerator.Current;
headA.Dump("A");
headB.Dump("B");
Action reportDeletion = () => {
o.OnNext(Tuple.Create(indexA, false));
aHasNext = aEnumerator.MoveNext(); // this one is fast
};
Action reportInsertion = () => {
o.OnNext(Tuple.Create(indexB, true));
bHasNext = bEnumerator.MoveNext(); // can take a long time
};
if (headA == null) { // No source item at this position
reportInsertion();
continue;
}
if (headB == null) { // No fetched item at this position
reportDeletion();
continue;
}
switch (headB.Value.CompareTo(headA.Value)) {
case 0:
aHasNext = aEnumerator.MoveNext();
bHasNext = bEnumerator.MoveNext();
indexA++;
indexB++;
break;
case 1: // Fetched item is newer than source item
reportInsertion();
indexB++;
break;
case -1: // Source item is newer than fetched item
reportDeletion();
indexA++;
break;
}
}
return Disposable.Empty;
});
return observable;
}
void Main()
{
var a=新的整数?[{150,100,70,30,20};
VarB=新的整数?[{30020010070,60,50,20};
var结果=指数delta(a,b);
result.Dump();
}
//在此处定义其他方法和类
IObservable IndexDelta(IEnumerable a,IEnumerable b)
{
var observable=observable.Create(o=>{
var indexA=0;
var-indexB=0;
var aEnumerator=a.GetEnumerator();
var bEnumerator=b.GetEnumerator();
var aHasNext=aEnumerator.MoveNext();
var bHasNext=bEnumerator.MoveNext();
while(true){
if(aHasNext==false&&bHasNext==false){
“已完成”。转储();
o、 OnCompleted();//两个序列都结束了
打破
}
var headA=分子电流;
var headB=断路器电流;
标题A.垃圾场(“A”);
标题B.垃圾场(“B”);
操作报告删除=()=>{
o、 OnNext(Tuple.Create(indexA,false));
aHasNext=aEnumerator.MoveNext();//这个很快
};
动作报告插入=()=>{
o、 OnNext(Tuple.Create(indexB,true));
bHasNext=贝努美特。
IObservable<Tuple<int, bool>> IndexDelta(a, b)
{
var indexA = 0;
var indexB = 0;
while (true) {
var headA = a.Current;
var headB = b.Current;
if (headA == null && headB == null) {
return yield break; // both sequences are over
}
var reportDeletion = () => {
yield push Tuple.Create(indexA, false);
await a.MoveNext(); // this one is fast
}
var reportInsertion = () => {
yield push Tuple.Create(indexB, true);
await b.MoveNext(); // can take a long time
}
if (headA == null) { // No source item at this position
reportInsertion();
continue;
}
if (headB == null) { // No fetched item at this position
reportDeletion();
continue;
}
switch (headB.CompareTo(headA)) {
case 0:
yield continue;
break;
case 1: // Fetched item is newer than source item
reportInsertion();
break;
case -1: // Source item is newer than fetched item
reportDeletion();
break;
}
indexA++;
indexB++;
}
}
void Main()
{
var a = new int?[] {150, 100, 70, 30, 20 };
var b = new int?[] {300, 200, 100, 70, 60, 50, 20 };
var result = IndexDelta(a, b);
result.Dump();
}
// Define other methods and classes here
IObservable<Tuple<int, bool>> IndexDelta(IEnumerable<int?> a, IEnumerable<int?> b)
{
var observable = Observable.Create<Tuple<int, bool>>(o => {
var indexA = 0;
var indexB = 0;
var aEnumerator = a.GetEnumerator();
var bEnumerator = b.GetEnumerator();
var aHasNext = aEnumerator.MoveNext();
var bHasNext = bEnumerator.MoveNext();
while(true) {
if (aHasNext == false && bHasNext == false) {
"Completed".Dump();
o.OnCompleted(); // both sequences are over
break;
}
var headA = aEnumerator.Current;
var headB = bEnumerator.Current;
headA.Dump("A");
headB.Dump("B");
Action reportDeletion = () => {
o.OnNext(Tuple.Create(indexA, false));
aHasNext = aEnumerator.MoveNext(); // this one is fast
};
Action reportInsertion = () => {
o.OnNext(Tuple.Create(indexB, true));
bHasNext = bEnumerator.MoveNext(); // can take a long time
};
if (headA == null) { // No source item at this position
reportInsertion();
continue;
}
if (headB == null) { // No fetched item at this position
reportDeletion();
continue;
}
switch (headB.Value.CompareTo(headA.Value)) {
case 0:
aHasNext = aEnumerator.MoveNext();
bHasNext = bEnumerator.MoveNext();
indexA++;
indexB++;
break;
case 1: // Fetched item is newer than source item
reportInsertion();
indexB++;
break;
case -1: // Source item is newer than fetched item
reportDeletion();
indexA++;
break;
}
}
return Disposable.Empty;
});
return observable;
}
IObservable<Tuple<int, T, bool>> IndexDelta<T>(
IObservable<T> first, IObservable<T> second
)
where T : IComparable, IEquatable<T>
{
return Observable.Create<Tuple<int, T, bool>> (o => {
var a = first.ToEnumerable ().GetEnumerator ();
var b = second.ToEnumerable ().GetEnumerator ();
var indexA = -1;
var indexB = -1;
var hasNextA = true;
var hasNextB = true;
var headA = default(T);
var headB = default(T);
Action<bool> advanceA = (bool reportDeletion) => {
if (reportDeletion) {
o.OnNext (Tuple.Create (indexA, headA, false));
}
if (hasNextA = a.MoveNext ()) {
indexA++;
headA = a.Current;
}
};
Action<bool> advanceB = (bool reportInsertion) => {
if (reportInsertion) {
o.OnNext (Tuple.Create (indexB, headB, true));
}
if (hasNextB = b.MoveNext ()) {
indexB++;
headB = b.Current;
}
};
advanceA (false);
advanceB (false);
while (true) {
if (!hasNextA && !hasNextB) {
o.OnCompleted ();
break;
}
if (!hasNextA) {
advanceB (true);
continue;
}
if (!hasNextB) {
advanceA (true);
continue;
}
switch (headA.CompareTo (headB)) {
case 0:
advanceA (false);
advanceB (false);
break;
case 1:
advanceA (true);
break;
case -1:
advanceB (true);
break;
}
}
return Disposable.Create (() => {
a.Dispose ();
b.Dispose ();
});
});
}