我们知道,我们可以使用ObservableCollection来观察集合的变化。
没关系。
但是如何处理ImmutableList改变了?
例如:我有IObservable<ImmutableArray<int>>
和这个蒸汽序列可能:
首先:1,2,3,4,5
第二:1,2,3,4,5,6&lt; ----(绑定到视图时可能会遇到一些性能问题。)
第三名:3,4
是否有任何优雅的方式(或某些库)可以转换IObservable<ImmutableArray<int>> to ObservableCollection<int> ?
然后我们可以观察ObservableCollection通知事件:
首先:添加事件1,2,3,4,5
第二:添加事件6,7&lt; ----(很酷!)
第三:删除事件1,2,5,6
非常感谢。
答案 0 :(得分:2)
这可能是一种天真的做法,但这是你想到的那种事情吗?
source
.Subscribe(ia =>
{
var ia2 = ia.ToArray();
var adds = ia2.Except(oc).ToArray();
var removes = oc.Except(ia2).ToArray();
foreach (var a in adds)
{
oc.Add(a);
}
foreach (var r in remove)
{
oc.Remove(r);
}
});
答案 1 :(得分:0)
经过一些研究,我有一个回答我自己的问题。
最佳解决方案应为Levenshtein distance。
计算过程大致如下:
确定插入删除替换成本。 (insert = 1,delete = 1,substitution = 2)
计算levenshtein距离并得到矩阵。
用于最短路径和对齐的Backtrace矩阵。 (它非常像A *寻路,在生成矩阵时设置回溯点并在回溯后获得最佳路径)
因此,这个问题可能会被关闭。
答案 2 :(得分:0)
我实际上写了一个nuget包,可以自动为你做这个
https://github.com/Weingartner/ReactiveCompositeCollections
部分代码使用不可变列表之间的差异来生成ObservableCollection更改事件。
进行差异化的代码使用DiffLib
public static IObservable<List<DiffElement<T>>>
ChangesObservable<T>
( this ICompositeList<T> source
, IEqualityComparer<T>comparer = null
)
{
return source
.Items // IObservable<ImmutableList<T>>
.StartWith(ImmutableList<T>.Empty)
.Buffer(2, 1).Where(b => b.Count == 2)
.Select(b =>
{
var sections = Diff.CalculateSections(b[0], b[1], comparer);
var alignment = Diff.AlignElements
(b[0], b[1], sections, new BasicReplaceInsertDeleteDiffElementAligner<T>());
return alignment.ToList();
});
}
在另一种方法中可以转换为ObservableCollection
internal ReadOnlyObservableCollection
( ICompositeList<T> list
, System.Collections.ObjectModel.ObservableCollection<T> collection
, IEqualityComparer<T> eq
) : base(collection)
{
_List = list;
_Collection = collection;
_Disposable = list.ChangesObservable(eq)
.Subscribe(change =>
{
int i = 0;
foreach (var diff in change)
{
switch (diff.Operation)
{
case DiffOperation.Match:
break;
case DiffOperation.Insert:
_Collection.Insert(i, diff.ElementFromCollection2.Value);
break;
case DiffOperation.Delete:
_Collection.RemoveAt(i);
i--;
break;
case DiffOperation.Replace:
_Collection[i] = diff.ElementFromCollection2.Value;
break;
case DiffOperation.Modify:
_Collection[i] = diff.ElementFromCollection2.Value;
break;
default:
throw new ArgumentOutOfRangeException();
}
i++;
}
});
}