对于我在这里的第一篇文章,我有一个关于IEnumerable比较的问题。 我有一个基于枚举逻辑的可绑定结构。 IEnumerable的内容随着时间的推移而变化,我必须手动触发CollectionChanged事件。
我有一个非常天真的算法,它允许我检测IEnumerable的两个状态之间的简单更改(简单添加,简单删除,多次添加,多次删除)但它不是非常有效并且不会检测到所有内容。
我需要的一个简单示例:
IEnumerable的状态1: A * B * C * D * E
IEnumerable的状态2: A * C * B * D * D1
对于这个例子,我必须检测
是否有算法尽可能有效地解决这个问题(O(nLog(n))会是一个好的开始)?
谢谢!
答案 0 :(得分:1)
如果您更喜欢使用Linq,这里有一个基于您的示例的简单解决方案..抱歉但不确定性能..
var a = new List<string>{"A","B","C","D","E"};
var b = new List<string>{"A","C","B","D","D1"};
var removed = a.Except(b);
var moved = a.Where(x => b[a.IndexOf(x)] != x && !removed.Contains(x));
List<string> newlyInserted = new List<string>();
foreach (var item in removed)
{
//Newly inserted into the list - D1
newlyInserted.Add(b[a.IndexOf(item)]);
//Index of D1 if required
var indexOfNewlyAddedItem = a.IndexOf(item);
}
或只是
var newlyAdded = b.Except(a);
答案 1 :(得分:1)
这是未经编译的,未经测试且至少部分伪造的代码。
鉴于单个移动检测已足够物品只能向前移动,向后移动将是移动或移除另一个物品的结果
e.g。 IEnumerable的状态1:A * B * C * D * E
IEnumerable的状态2:A * D * B * C * D1
结果B和C都向前发展。
enum1pos = -1;
enum2pos = 0;
Value2 = enum2.Next()
enum2pos++;
List<int> SkipList = new SkipList();
while(enum1 has values left)
{
Value1 = enum1.Next()
enum1pos++;
//Skip over moved items.
while (SkipList.Count > 0 && SkipList[0] == enum2.Position)
{
Value2 = enum2.Next()
enum2pos++;
}
if (Value1 == Value2)
Value2 = enum2.Next()
enum2pos++;
continue;
int temp = enum2pos;
while(Value1 !=Value and enum2 has more values)
{
Value2 = enum2.Next();
enum2pos++;
}
if(Value1 != Value2)
ItemDeleted(Value1);
else
{
ItemMoved(Value1, enum2pos);
SkipList.Add(enum2pos);
}
//This is expensive for IEnumerable!
enum2.First();
loop temp times
enum2.Next();
//if
}
while (enum2 has values left)
{
while (SkipList.Count > 0 && SkipList[0] == enum2.Position)
{
Value2 = enum2.Next()
enum2pos++;
}
if (enum2 has values left)
Added(Value2, enum2pos)
}
结果:
比较A和A
接下来
比较B和D
找到B
B已移动 - &gt; 2
将2添加到跳过列表
重置枚举2
比较C和D
找到C
C Moved - &gt; 3
将3添加到跳过列表中
重置枚举2
接下来
比较D和D
接下来
跳过(2)
跳过(3)
比较E和D1
找到E
删除(E)
接下来
Enum结束
加入(D1,4)
我认为如果enum2pos太过落后,看看它是否已被移除,并且如果它没有为它在enum1中的原始位置添加跳过,则会有一个保存,这将有助于enum2的位置被重置所有的时间。