可观察对象顺序在.net中设置

本文关键字:net 设置 顺序 观察 对象 | 更新日期: 2023-09-27 18:12:54

我需要一个按顺序排列的集合,就像一个列表。

集合也可以是可观察的。

任何建造。在。net 4中是这样的吗?

可观察对象顺序在.net中设置

据我所知,在。net中没有这样的类型。我最近需要这个,并最终自己实现了它;没那么难。

技巧是将Dictionary<T, LinkedListNode<T>>LinkedList<T>结合起来。使用字典在O(1)时间内查询键和值,并按插入顺序迭代列表。你需要一个字典而不是一个集合,因为你想要能够调用LinkedList<T>.Remove(LinkedListNode<T>)而不是LinkedList<T>.Remove(T)。前者的时间复杂度为O(1),后者为O(n)。

听起来你需要ReadOnly Queue。在。net中,我们内置了Queue类,但是没有内置ReadOnly Queue。要确保没有重复的值,可以使用contains check

有一个Nuget包具有ImmutableQueue。不确定它能不能帮到你。这将在每次Enqueue或Dequeue操作完成时创建新的Queue对象。https://msdn.microsoft.com/en-us/library/dn467186 (v = vs.111) . aspx

我想你可以使用SortedDictionary<>Dictionary<>一起做这个。

假设您永远不会在集合中进行超过int.MaxValue的插入,您可以使用整数"序列号"作为SortedDictionary的键,以跟踪按插入顺序插入的项。

除此之外,您还需要使用Dictionary将项目映射到用于插入它们的序列号。

把这些放到一个类和一个演示程序中:(不是线程安全的!)

using System;
using System.Collections;
using System.Collections.Generic;
namespace Demo
{
    public sealed class SequencedSet<T>: IEnumerable<T>
    {
        private readonly SortedDictionary<int, T> items = new SortedDictionary<int, T>();
        private readonly Dictionary<T, int> order = new Dictionary<T, int>();
        private int sequenceNumber = 0;
        public void Add(T item)
        {
            if (order.ContainsKey(item))
                return; // Or throw if you want.
            order[item] = sequenceNumber;
            items[sequenceNumber] = item;
            ++sequenceNumber;
        }
        public void Remove(T item)
        {
            if (!order.ContainsKey(item))
                return; // Or throw if you want.
            int sequence = order[item];
            items.Remove(sequence);
            order.Remove(item);
        }
        public bool Contains(T item)
        {
            return order.ContainsKey(item);
        }
        public IEnumerator<T> GetEnumerator()
        {
            return items.Values.GetEnumerator();
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
    internal class Program
    {
        private static void Main()
        {
            var test = new SequencedSet<string>();
            test.Add("One");
            test.Add("Two");
            test.Add("Three");
            test.Add("Four");
            test.Add("Five");
            test.Remove("Four");
            test.Remove("Two");
            foreach (var item in test)
                Console.WriteLine(item);
        }
    }
}

对于插入和删除来说,这应该是相当高效的,但它当然会占用两倍的内存。如果你要做大量的插入和删除,你可以使用long而不是int作为序列号。

不幸的是,如果你做了超过2^63的删除,即使这将不起作用-尽管我认为这应该是足够的…