Set collection preserving insertion order
I need a collection that behaves as Set and preserves order of element insertion.
Is there one or I'll have to implement it myself?
What would th开发者_Python百科e best implementation be?
It doesn't exist in .NET, but you can emulate it using a List
and the Distinct
LINQ extension method, which should preserve the order of the underlying List
.
Will an OrderedDictionary
do what you want?
Although it is not generic (meaning everything it returns has to be cast or unboxed) and is a dictionary (not a set), it will behave the way you want. You could easily just use some arbitrary value like null
or true
as values and let the keys be the members of your set.
Here's a possible implementation:
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; } }
}
It is easy to create one:
public class InsertionOrderSet<T> : KeyedCollection<T,T>
{
protected override T GetKeyForItem(T item)
{
return item;
}
}
Caveat: Inserting duplicate items via .Add(T)
will result in ArgumentException
s, which differs from, say, a HashSet<T>
which will just return false
in that case.
List inCountryList = new ArrayList(); . . . Set countrySet = new LinkedHashSet( inCountryList );
LinkedHashSet doesn't allow duplication, nad maintain insertion order.
I realize this is an old post, but I had a need for something similar recently, and thought this implementation might help if someone wants a generic sequence that maintains the order items are added (as well as lets you insert before and after any given item). I'm sure someone has more efficient ways to get this done, but this does the trick.
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;
}
}
}
精彩评论