Это некомпилированный, непроверенный и, по крайней мере, частично псевдо-код.
При достаточном обнаружении одного движения Предметы могут двигаться только вперед, перемещение назад будет результатом перемещения или удаления другого элемента
например, Состояние 1 IEnumerable: A * B * C * D * E
Состояние 2 IEnumerable: 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 Moved -> 2
Добавить 2 в ПропуститьСписок
Сброс Enum2
Сравнение C и D
Поиск C
C Перемещение -> 3
Добавление 3 в список пропуска
Сброс Enum2
Далее
Сравнение D и D
Далее
Пропустить (2)
Пропустить (3)
Сравнить E и D1
Найти E
Удалено (E)
Далее
Добавлен конец Enum1 (D1, 4)
Я думаю, что где-то есть экономия, если enum2pos слишком далеко отстает, чтобы увидеть, был ли он удален, и если он не добавил пропуска для своей исходной позиции в enum1, этопоможет с постоянным сбросом позиции enum2.