2010-03-05 10 views
5

Necesito una colección que se comporte como Establecida y preserve el orden de inserción del elemento.Establecer el orden de inserción de preservación de la colección

¿Hay uno o tendré que implementarlo yo mismo?

¿Cuál sería la mejor implementación?

+0

¿Cómo funcionaría una colección así? Si inserta un elemento como primer elemento y luego lo inserta 20 iteraciones más tarde, ¿debería ser el elemento 1 o el elemento 20? – Aaronaught

+0

Para mi tarea, necesito que sea el elemento 1. –

Respuesta

2

No existe en .NET, pero se puede emular el uso de un método de extensión y la Distinct LINQ List, que debe preservar el orden de la List subyacente.

+0

Es extremadamente frustrante ¿no? La misma frustración en PowerShell que utiliza Hashtable para diccionarios que también pierde el orden de inserción. – Josh

+0

Necesito indexación rápida, pero puedo permitir inserciones lentas, así que recurriré a 'List' y escribiré el método de extensión' AddUnique' para lograr establecer la semántica. –

+1

El 'Distinct' de LINQ conserva el orden tal como está implementado actualmente, pero la [documentación de MSDN] (http://msdn.microsoft.com/en-us/library/bb348436.aspx) indica específicamente que no está ordenada. Proceda con precaución. –

2

¿Va a hacer OrderedDictionary lo que quiere?

Aunque no es genérico (significa que todo lo que devuelve tiene que ser lanzado o no) y es un diccionario (no un conjunto), se comportará de la manera que desee. Simplemente podría usar algún valor arbitrario como null o true como valores y dejar que las claves sean los miembros de su conjunto.

He aquí una posible implementación:

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; } } 
} 
+1

Funcionará, pero básicamente tendría que usar las claves y no los valores. No es ideal, pero hará el trabajo. –

0

Lista inCountryList = new ArrayList(); . . . Establecer countrySet = new LinkedHashSet (inCountryList);

LinkedHashSet no permite la duplicación, nad mantener el orden de inserción.

1

Es fácil crear una:

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

Advertencia: Inserción de elementos duplicados a través de .Add(T) dará lugar a ArgumentException s, lo que difiere de, digamos, un HashSet<T> que acaba de regresar false en ese caso.

0

Me doy cuenta de que esta es una publicación anterior, pero tuve la necesidad de algo similar recientemente, y pensé que esta implementación podría ayudar si alguien quiere una secuencia genérica que mantiene el orden de los elementos agregados (y le permite insertar antes y después de cualquier artículo dado). Estoy seguro de que alguien tiene formas más eficientes de hacer esto, pero esto funciona.

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; 
     } 
    } 
} 
Cuestiones relacionadas