2010-03-05 3 views
5

세트로 작동하고 요소 삽입 순서를 유지하는 콜렉션이 필요합니다.삽입 순서를 유지하는 콜렉션을 설정하십시오.

직접 구현해야합니까? 아니면 직접 구현해야합니까?

최상의 구현 방법은 무엇입니까?

+0

어떻게 그러한 컬렉션이 작동합니까? 첫 번째 요소로 하나의 요소를 삽입 한 다음 요소 1 또는 요소 20이면 20 회 반복하십시오. – Aaronaught

+0

제 일을 위해 나는 그것이 요소 1이 될 필요가 있습니다. –

답변

2

.NET에는 존재하지 않지만 ListDistinct LINQ 확장 메서드를 사용하여 에뮬레이션 할 수 있습니다.이 메서드는 기본이되는 List의 순서를 유지해야합니다.

+0

그것은 극도로 좌절하지 않습니까? 삽입 순서를 잃어 버리는 사전에 Hashtable을 사용하는 PowerShell에서도 같은 좌절감을 느낍니다. – Josh

+0

빠른 인덱싱이 필요하지만 느린 삽입을 허용 할 수 있으므로'List'를 사용하고 Set 메서드를 구현하는 확장 메서드'AddUnique'를 작성합니다. –

+1

LINQ의 Distinct는 현재 구현 된대로 순서를 유지하지만 [MSDN 설명서] (http://msdn.microsoft.com/en-us/library/bb348436.aspx)에는 순서가 지정되지 않았다고 명시되어 있습니다. 조심해서 진행해라. –

2

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

작동하지만 기본적으로 키만 사용하고 값은 사용하지 않아야합니다. 이상적은 아니지만 일을 끝내게됩니다. –

0

목록 inCountryList = 새로운 ArrayList를(); . . . Set countrySet = 새 LinkedHashSet (inCountryList);

LinkedHashSet은 삽입 순서를 유지하지 않고 복제를 허용하지 않습니다.

1

그것은 하나를 쉽게 만들 수 있습니다 :

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

주의 할 : .Add(T)를 통해 중복 항목을 삽입하는 것은 바로이 경우에 false을 반환하는 HashSet<T>, 말, 다르다 ArgumentException의, 발생합니다.

0

나는 이것이 오래된 게시물이라는 것을 알고 있지만, 최근 비슷한 비슷한 것을 필요로했다. 누군가가 주문 항목을 유지 관리하는 일반적인 시퀀스를 원한다면이 구현이 도움이된다고 생각했다. 주어진 항목 이후). 나는 누군가가 이것을 할 수있는보다 효율적인 방법을 가지고 있다고 확신하지만, 이것은 속임수입니다.

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; 
     } 
    } 
} 
관련 문제