代码之家  ›  专栏  ›  技术社区  ›  Konstantin Spirin

设置保留插入顺序的集合

  •  5
  • Konstantin Spirin  · 技术社区  · 15 年前

    我需要一个集合,它的行为和设置一样,并保持元素插入的顺序。

    有没有,还是我自己来实施?

    最好的实现是什么?

    5 回复  |  直到 11 年前
        1
  •  2
  •   David Pfeffer    15 年前

    它在.NET中不存在,但您可以使用 List 以及 Distinct Linq扩展方法,它应该保留底层的顺序 .

        2
  •  2
  •   Gabe Timothy Khouri    15 年前

    将一个 OrderedDictionary 做你想做的?

    虽然它不是通用的(意味着它返回的所有内容都必须被强制转换或取消绑定),并且是一个字典(不是一个集合),但它将按您想要的方式工作。你可以很容易地使用一些任意的值,比如 null true 作为值并让键成为集合的成员。

    下面是一个可能的实现:

    public class OrderedSet : ICollection, IEnumerable
    {
        OrderedDictionary dict = new OrderedDictionary();
        public void Add(object member)
        {
            dict.Add(member, null);
        }
        public void Clear()
        {
            dict.Clear();
        }
        public void CopyTo(Array array, int index)
        {
            for (int i = 0; i < Count; i++)
                array[i + index] = dict[i];
        }
        public bool Contains(object member)
        {
            return dict.Contains(member);
        }
        public void Insert(int index, object member)
        {
            dict.Insert(index, member, null);
        }
        public void Remove(object member)
        {
            dict.Remove(member);
        }
        public void RemoveAt(int index)
        {
            dict.RemoveAt(index);
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return dict.Keys.GetEnumerator();
        }
    
        public int Count { get { return dict.Count; } }
        public ICollection Members { get { return dict.Keys; } }
        bool ICollection.IsSynchronized { get { return dict.IsSynchronized; } }
        object ICollection.SyncRoot { get { return dict.SyncRoot; } }
    }
    
        3
  •  1
  •   Evgeniy Berezovsky    11 年前

    很容易创建一个:

    public class InsertionOrderSet<T> : KeyedCollection<T,T>
    {
        protected override T GetKeyForItem(T item)
        {
            return item;
        }
    }
    

    告诫 :通过插入重复项 .Add(T) 会导致 ArgumentException S,它不同于,比方说,A HashSet<T> 它会回来的 false 在这种情况下。

        4
  •  0
  •   Prosenjit Mondal    13 年前

    list incountrylist=new arraylist(); . . . set countryset=new linkedhashset(incountrylist);

    linkedhashset不允许重复,nad保持插入顺序。

        5
  •  0
  •   Mitchell Lee    11 年前

    我意识到这是一篇旧文章,但是最近我需要类似的东西,并且认为如果有人想要一个维护订单项添加的通用序列(以及允许您在任何给定项之前和之后插入),这个实现可能会有所帮助。我相信有人有更有效的方法来完成这项工作,但这确实有诀窍。

    public class Sequence<T> : ICollection<T>
    {
        private readonly SortedList<long, T> _baseList;
    
        public Sequence()
        {
            this._baseList = new SortedList<long, T>();
        }
    
        public IEnumerator<T> GetEnumerator()
        {
            return this._baseList.Values.GetEnumerator();
        }
    
        IEnumerator IEnumerable.GetEnumerator()
        {
            return this.GetEnumerator();
        }
    
        public void Add(T item)
        {
            this._baseList.Add(this._baseList.Count(), item);
        }
    
        public void AddAfter(T item, T newItem)
        {
            var currentIndex = this._baseList.IndexOfValue(item);
            if (currentIndex == _baseList.Count())
            {
                this.Add(newItem);
            }
            else
            {
                var itemsToMove = new SortedList<long, T>();
                var total = Count;
                for (var i = currentIndex + 1; i < total; i++)
                {
                    itemsToMove.Add(i, _baseList[i]);
                    _baseList.Remove(i);
                }
    
                this.Add(newItem);
                foreach (var itemToMove in itemsToMove)
                {
                    this.Add(itemToMove.Value);
                }
            }
        }
    
        public void AddBefore(T item, T newItem)
        {
            var currentIndex = this._baseList.IndexOfValue(item);
            var itemsToMove = new SortedList<long, T>();
            var total = Count;
            for (var i = currentIndex; i < total; i++)
            {
                itemsToMove.Add(i, this._baseList[i]);
                _baseList.Remove(i);
            }
    
            this.Add(newItem);
            foreach (var itemToMove in itemsToMove.Values)
            {
                this.Add(itemToMove);
            }
        }
    
        public void Clear()
        {
            this._baseList.Clear();
        }
    
        public bool Contains(T item)
        {
            return this._baseList.ContainsValue(item);
        }
    
        public void CopyTo(T[] array, int arrayIndex)
        {
            this._baseList.Values.CopyTo(array, arrayIndex);
        }
    
        public bool Remove(T item)
        {
            try
            {
                this._baseList.RemoveAt(this._baseList.IndexOfValue(item));
                return true;
            }
            catch
            {
                return false;
            }
        }
    
        public int Count
        {
            get
            {
                return this._baseList.Count();
            }
        }
    
        public bool IsReadOnly
        {
            get
            {
                return false;
            }
        }
    }
    
    推荐文章