设置集合保留插入顺序

发布于 2024-08-23 21:06:12 字数 75 浏览 3 评论 0原文

我需要一个行为类似于 Set 并保留元素插入顺序的集合。

有没有或者我必须自己实现?

最好的实施是什么?

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 the best implementation be?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

清晰传感 2024-08-30 21:06:12

它在 .NET 中不存在,但您可以使用 ListDistinct LINQ 扩展方法来模拟它,这应该保留底层 List 的顺序

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.

も星光 2024-08-30 21:06:12

OrderedDictionary 做你想做的事?

尽管它不是通用的(意味着它返回的所有内容都必须进行强制转换或拆箱)并且是一个字典(不是集合),但它会按照您想要的方式运行。您可以轻松地使用一些任意值(例如 nulltrue)作为值,并让键成为集合的成员。

这是一个可能的实现:

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

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; } }
}
醉生梦死 2024-08-30 21:06:12

创建一个很容易:

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

警告:通过 .Add(T) 插入重复项将导致 ArgumentException,这与其他情况不同,一个 HashSet 在这种情况下只会返回 false

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 ArgumentExceptions, which differs from, say, a HashSet<T> which will just return false in that case.

ぃ双果 2024-08-30 21:06:12

List inCountryList = new ArrayList();



设置 CountrySet = new LinkedHashSet( inCountryList );

LinkedHashSet 不允许重复,且不能保持插入顺序。

List inCountryList = new ArrayList();
.
.
.
Set countrySet = new LinkedHashSet( inCountryList );

LinkedHashSet doesn't allow duplication, nad maintain insertion order.

沩ん囻菔务 2024-08-30 21:06:12

我意识到这是一篇旧帖子,但我最近需要类似的东西,并且认为如果有人想要一个维护添加顺序项目的通用序列(以及允许您在任何给定项目之前和之后插入),那么此实现可能会有所帮助)。我确信有人有更有效的方法来完成这项工作,但这确实有效。

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

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;
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文