private static List <MergeRecord> RemoveOldValues(List <T> remainings, List <T> others, out List <int> existingPositions)
        {
            var result     = new List <MergeRecord>();
            var i          = 0;
            var dictionary = others.SafeToDictionary(item => item, item => i++);
            var othersSet  = others.ToHashSet();

            existingPositions = new List <int>();
            MergeRecord currentMergeRecord = null;
            var         index = 0;
            var         array = remainings.ToArray();

            remainings.Clear();
            foreach (var item in array)
            {
                if (!othersSet.Contains(item))
                {
                    if (currentMergeRecord == null)
                    {
                        currentMergeRecord = new MergeRecord();
                        currentMergeRecord.Update(item, false, index++);
                        result.Add(currentMergeRecord);
                    }
                    else
                    {
                        currentMergeRecord.Update(item);
                        index++;
                    }
                }
                else
                {
                    existingPositions.Add(dictionary[item]);
                    remainings.Add(item);
                    index++;
                    if (currentMergeRecord != null)
                    {
                        index -= currentMergeRecord.Items.Count;
                        currentMergeRecord = null;
                    }
                }
            }
            return(result);
        }
Exemple #2
0
        protected override IEnumerable <MergeRecord> UpdateOverride(IEnumerable <T> others)
        {
            if (others == null)
            {
                Clear();
                return(Enumerable.Empty <MergeRecord>());
            }

            var myEnumerator    = GetEnumerator();
            var othersArray     = others as T[] ?? others.ToArray();
            var otherEnumerator = othersArray.GetEnumerator();
            var thisHas         = myEnumerator.MoveNext();
            var otherHas        = otherEnumerator.MoveNext();

            if (!thisHas && otherHas)
            {
                ViewArray = (T[])othersArray.Clone();
                return(new List <MergeRecord> {
                    new MergeRecord {
                        StartIndex = 0, IsAdd = true, Items = ViewArray
                    }
                });
            }
            if (thisHas && !otherHas)
            {
                var oldItems = ViewArray;
                ViewArray = new T[0];
                return(new List <MergeRecord> {
                    new MergeRecord {
                        StartIndex = 0, IsAdd = false, Items = oldItems
                    }
                });
            }
            var         newArray      = new T[othersArray.Count()];
            var         index         = 0;
            MergeRecord currentRecord = null;
            var         result        = new List <MergeRecord>();

            while (thisHas && otherHas)
            {
                var myItem        = myEnumerator.Current;
                var otherItem     = (T)otherEnumerator.Current;
                var compareResult = Comparison(myItem, otherItem);
                if (compareResult < 0)
                {
                    if (currentRecord == null || currentRecord.IsAdd)
                    {
                        var isAdd = currentRecord != null;
                        currentRecord = new MergeRecord();
                        result.Add(currentRecord);
                        currentRecord.Update(myItem, false, index + (isAdd ? 1 : 0));
                    }
                    else
                    {
                        currentRecord.Update(myItem);
                    }

                    thisHas = myEnumerator.MoveNext();
                }
                else if (compareResult > 0)
                {
                    if (currentRecord == null || !currentRecord.IsAdd)
                    {
                        currentRecord = new MergeRecord();
                        result.Add(currentRecord);
                        currentRecord.Update(otherItem, true, index);
                    }
                    else
                    {
                        currentRecord.Update(otherItem);
                    }

                    newArray[index++] = otherItem;
                    otherHas          = otherEnumerator.MoveNext();
                }
                else
                {
                    if (!Equals(myItem, otherItem))
                    {
                        if (currentRecord == null || !currentRecord.IsReplace)
                        {
                            currentRecord = new MergeRecord();
                            result.Add(currentRecord);
                            currentRecord.UpdateReplace(myItem, otherItem, index);
                        }
                        else
                        {
                            currentRecord.UpdateReplace(myItem, otherItem);
                        }
                        newArray[index++] = otherItem;
                    }
                    else
                    {
                        currentRecord   = null;
                        newArray[index] = otherItem;
                        index++;
                    }
                    thisHas  = myEnumerator.MoveNext();
                    otherHas = otherEnumerator.MoveNext();
                }
            }
            // Se acabó el primero pero le queda al segundo
            if (otherHas)
            {
                if (currentRecord == null || currentRecord.IsReplace || !currentRecord.IsAdd)
                {
                    currentRecord = new MergeRecord {
                        IsAdd = true, StartIndex = index
                    };
                    result.Add(currentRecord);
                }
                while (otherHas)
                {
                    var current = (T)otherEnumerator.Current;
                    newArray[index++] = current;
                    currentRecord.Update(current);
                    otherHas = otherEnumerator.MoveNext();
                }
            }
            // Se acabó el segundo pero le queda al primero
            if (thisHas)
            {
                if (currentRecord == null || currentRecord.IsReplace || currentRecord.IsAdd)
                {
                    currentRecord = new MergeRecord {
                        IsAdd = false, StartIndex = index
                    };
                    result.Add(currentRecord);
                }
                while (thisHas)
                {
                    currentRecord.Update(myEnumerator.Current);
                    thisHas = myEnumerator.MoveNext();
                }
            }
            ViewArray = newArray;
            return(result);
        }