Beispiel #1
0
        public IChangeSet <TObject, TKey> Reorder()
        {
            var result = new List <Change <TObject, TKey> >();

            if (_optimisations.HasFlag(SortOptimisations.IgnoreEvaluates))
            {
                //reorder entire sequence and do not calculate moves
                _list = _list.OrderBy(kv => kv, _comparer).ToList();
            }
            else
            {
                var index         = -1;
                var sorted        = _list.OrderBy(t => t, _comparer).ToList();
                var unsortedCache = _list.Select((kvp, idx) => new { kvp, idx }).ToDictionary(o => o.kvp, o => o.idx);

                foreach (var item in sorted)
                {
                    index++;

                    var oldPos = unsortedCache[item];

                    if (oldPos == index)
                    {
                        continue;
                    }

                    result.Add(new Change <TObject, TKey>(item.Key, item.Value, index, oldPos));
                }

                _list = sorted;
            }

            return(new ChangeSet <TObject, TKey>(result));
        }
Beispiel #2
0
        public IChangeSet <TObject, TKey> Reorder()
        {
            var result = new List <Change <TObject, TKey> >();

            if (_optimisations.HasFlag(SortOptimisations.IgnoreEvaluates))
            {
                //reorder entire sequence and do not calculate moves
                _list = new LinkedList <KeyValuePair <TKey, TObject> >(_list.OrderBy(kv => kv, _comparer));
            }
            else
            {
                var sorted   = _list.OrderBy(t => t, _comparer).Select((item, i) => Tuple.Create(item, i)).ToList();
                var oldByKey = _list.Select((item, i) => Tuple.Create(item, i)).ToDictionary(x => x.Item1.Key, x => x.Item2);

                foreach (var item in sorted)
                {
                    var currentItem  = item.Item1;
                    var currentIndex = item.Item2;

                    var previousIndex = oldByKey[currentItem.Key];

                    if (currentIndex != previousIndex)
                    {
                        result.Add(new Change <TObject, TKey>(currentItem.Key, currentItem.Value, currentIndex, previousIndex));
                    }
                }

                _list = new LinkedList <KeyValuePair <TKey, TObject> >(sorted.Select(s => s.Item1));
            }

            return(new ChangeSet <TObject, TKey>(result));
        }
        public IChangeSet <TObject, TKey> Reorder()
        {
            var result = new List <Change <TObject, TKey> >();

            if (_optimisations.HasFlag(SortOptimisations.IgnoreEvaluates))
            {
                //reorder entire sequence and do not calculate moves
                _list = _list.OrderBy(kv => kv, _comparer).ToList();
            }
            else
            {
                int index  = -1;
                var sorted = _list.OrderBy(t => t, _comparer).ToList();
                foreach (var item in sorted)
                {
                    KeyValuePair <TKey, TObject> current = item;
                    index++;

                    //Cannot use binary search as Resort is implicit of a mutable change
                    KeyValuePair <TKey, TObject> existing = _list[index];
                    var areequal = EqualityComparer <TKey> .Default.Equals(current.Key, existing.Key);

                    if (areequal)
                    {
                        continue;
                    }

                    var old = _list.IndexOf(current);
                    _list.RemoveAt(old);
                    _list.Insert(index, current);

                    result.Add(new Change <TObject, TKey>(current.Key, current.Value, index, old));
                }
            }

            return(new ChangeSet <TObject, TKey>(result));
        }
Beispiel #4
0
        /// <summary>
        /// Dynamic calculation of moved items which produce a result which can be enumerated through in order.
        /// </summary>
        /// <param name="changes">The change set.</param>
        /// <returns>A change set with the calculations.</returns>
        public IChangeSet <TObject, TKey> Calculate(IChangeSet <TObject, TKey> changes)
        {
            var result    = new List <Change <TObject, TKey> >(changes.Count);
            var refreshes = new List <Change <TObject, TKey> >(changes.Refreshes);

            foreach (var u in changes)
            {
                var current = new KeyValuePair <TKey, TObject>(u.Key, u.Current);

                switch (u.Reason)
                {
                case ChangeReason.Add:
                {
                    var position = GetInsertPositionBinary(current);
                    List.Insert(position, current);

                    result.Add(new Change <TObject, TKey>(ChangeReason.Add, u.Key, u.Current, position));
                }

                break;

                case ChangeReason.Update:
                {
                    var previous = new KeyValuePair <TKey, TObject>(u.Key, u.Previous.Value);
                    var old      = GetCurrentPosition(previous);
                    List.RemoveAt(old);

                    var newPosition = GetInsertPositionBinary(current);
                    List.Insert(newPosition, current);

                    result.Add(new Change <TObject, TKey>(ChangeReason.Update, u.Key, u.Current, u.Previous, newPosition, old));
                }

                break;

                case ChangeReason.Remove:
                {
                    var position = GetCurrentPosition(current);
                    List.RemoveAt(position);
                    result.Add(new Change <TObject, TKey>(ChangeReason.Remove, u.Key, u.Current, position));
                }

                break;

                case ChangeReason.Refresh:
                {
                    refreshes.Add(u);
                    result.Add(u);
                }

                break;
                }
            }

            // for evaluates, check whether the change forces a new position
            var evaluates = refreshes.OrderByDescending(x => new KeyValuePair <TKey, TObject>(x.Key, x.Current), _comparer).ToList();

            if (evaluates.Count != 0 && _optimisations.HasFlag(SortOptimisations.IgnoreEvaluates))
            {
                // reorder entire sequence and do not calculate moves
                List = List.OrderBy(kv => kv, _comparer).ToList();
            }
            else
            {
                // calculate moves.  Very expensive operation
                // TODO: Try and make this better
                foreach (var u in evaluates)
                {
                    var current = new KeyValuePair <TKey, TObject>(u.Key, u.Current);
                    var old     = List.IndexOf(current);
                    if (old == -1)
                    {
                        continue;
                    }

                    int newPosition = GetInsertPositionLinear(List, current);

                    if (old < newPosition)
                    {
                        newPosition--;
                    }

                    if (old == newPosition)
                    {
                        continue;
                    }

                    List.RemoveAt(old);
                    List.Insert(newPosition, current);
                    result.Add(new Change <TObject, TKey>(u.Key, u.Current, newPosition, old));
                }
            }

            return(new ChangeSet <TObject, TKey>(result));
        }