Установить порядок сохранения коллекции - PullRequest
5 голосов
/ 05 марта 2010

Мне нужна коллекция, которая ведет себя как Set и сохраняет порядок вставки элементов.

Есть ли такой, или мне придется самому его реализовать?

Какой будет лучшая реализация?

Ответы [ 5 ]

2 голосов
/ 05 марта 2010

Будет ли 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; } }
}
2 голосов
/ 05 марта 2010

Он не существует в .NET, но вы можете эмулировать его, используя List и Distinct метод расширения LINQ, который должен сохранить порядок базового List.

1 голос
/ 21 ноября 2013

Легко создать:

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

Предостережение : вставка дублирующихся элементов через .Add(T) приведет к ArgumentException с, что отличается, скажем, от HashSet<T>, который в этом случае просто вернет false.

0 голосов
/ 21 ноября 2013

Я понимаю, что это старый пост, но мне недавно было нужно что-то похожее, и я подумал, что эта реализация может помочь, если кто-то захочет добавить общую последовательность, которая поддерживает добавление элементов порядка (а также позволяет вставлять до и после любой данный пункт). Я уверен, что у кого-то есть более эффективные способы сделать это, но это помогает.

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;
        }
    }
}
0 голосов
/ 03 января 2012

Список inCountryList = new ArrayList (); , , , Установить countrySet = новый LinkedHashSet (inCountryList);

LinkedHashSet не разрешает дублирование, не поддерживает порядок вставки.

...