我需要一个行为为Set的集合,并保留元素插入的顺序。
是否有一个或我必须自己实施?
最佳实施是什么?
答案 0 :(得分:2)
它在.NET中不存在,但您可以使用List
和Distinct
LINQ扩展方法来模拟它,这应该保留基础List
的顺序。< / p>
答案 1 :(得分: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; } }
}
答案 2 :(得分:1)
创建一个很容易:
public class InsertionOrderSet<T> : KeyedCollection<T,T>
{
protected override T GetKeyForItem(T item)
{
return item;
}
}
警告:通过.Add(T)
插入重复的项目会产生ArgumentException
s,这与HashSet<T>
不同,后者将返回false
在那种情况下。
答案 3 :(得分:0)
列出inCountryList = new ArrayList(); 。 。 。 设置countrySet = new LinkedHashSet(inCountryList);
LinkedHashSet不允许复制,并且维护插入顺序。
答案 4 :(得分: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;
}
}
}