收集没有重复但有订单,快速收容检查和添加/删除

时间:2017-10-06 15:24:47

标签: c# collections

我正在寻找一个具有快速遏制检查和添加/删除方法的集合(如HashSet<T>,如果T已经很好地实现,则接近O(1)),但也有订单。这并不意味着索引访问 - 它只是意味着如果我迭代它,元素的顺序与我添加它们的顺序相同。

在C#中有类似的东西吗? HashSet<T>甚至可以做到这一点吗?(我在MSDN上找不到该信息,我检查了HashSet<T>HashSet<T>.GetEnumerator。)

如果没有,我正在考虑使用包含内部HashSet<T>和内部LinkedList<T>的类来实现它。在HashSet<T>公开枚举器时,LinkedList<T>会公开添加,删除和包含检查。

1 个答案:

答案 0 :(得分:0)

您似乎正在寻找OrderedDictionary

唯一的缺点是它不支持泛型,但你可以很容易地围绕它进行包装,或者只是将值转换为你需要的类型。

编辑:在评论中提及@Blorgbeard,您可以找到&#34; OrderedSet&#34;的实现。在another answer符合您的确切要求(并使用LinkedList<T>HashSet<T>完全实现),这可能对您有用。

这是他们的实施(学分转到原作者,而不是我

public class OrderedSet<T> : ICollection<T>
{
    private readonly IDictionary<T, LinkedListNode<T>> m_Dictionary;
    private readonly LinkedList<T> m_LinkedList;

    public OrderedSet()
        : this(EqualityComparer<T>.Default)
    {
    }

    public OrderedSet(IEqualityComparer<T> comparer)
    {
        m_Dictionary = new Dictionary<T, LinkedListNode<T>>(comparer);
        m_LinkedList = new LinkedList<T>();
    }

    public int Count
    {
        get { return m_Dictionary.Count; }
    }

    public virtual bool IsReadOnly
    {
        get { return m_Dictionary.IsReadOnly; }
    }

    void ICollection<T>.Add(T item)
    {
        Add(item);
    }

    public bool Add(T item)
    {
        if (m_Dictionary.ContainsKey(item)) return false;
        LinkedListNode<T> node = m_LinkedList.AddLast(item);
        m_Dictionary.Add(item, node);
        return true;
    }

    public void Clear()
    {
        m_LinkedList.Clear();
        m_Dictionary.Clear();
    }

    public bool Remove(T item)
    {
        LinkedListNode<T> node;
        bool found = m_Dictionary.TryGetValue(item, out node);
        if (!found) return false;
        m_Dictionary.Remove(item);
        m_LinkedList.Remove(node);
        return true;
    }

    public IEnumerator<T> GetEnumerator()
    {
        return m_LinkedList.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public bool Contains(T item)
    {
        return m_Dictionary.ContainsKey(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        m_LinkedList.CopyTo(array, arrayIndex);
    }
}