以C#表示堆栈上的范围?
我有一个程序,需要存储数据值并定期获取最后的“x”数据值 它最初认为堆栈是一种方法,但我需要能够看到的不仅仅是顶部的值——类似于PeekRange方法,在该方法中,我可以查看最后的“x”个值 目前,我只是使用一个列表,得到最后,比如说,20个值,如下所示:以C#表示堆栈上的范围?,c#,.net,data-structures,stack,C#,.net,Data Structures,Stack,我有一个程序,需要存储数据值并定期获取最后的“x”数据值 它最初认为堆栈是一种方法,但我需要能够看到的不仅仅是顶部的值——类似于PeekRange方法,在该方法中,我可以查看最后的“x”个值 目前,我只是使用一个列表,得到最后,比如说,20个值,如下所示: var last20 = myList.Skip(myList.Count - 20).ToList(); 该列表在程序运行时一直在增长,但我只需要最后20个值。有人能就更好的数据结构提出一些建议吗 我可能会使用一个。单独实现一个并不难,因
var last20 = myList.Skip(myList.Count - 20).ToList();
该列表在程序运行时一直在增长,但我只需要最后20个值。有人能就更好的数据结构提出一些建议吗 我可能会使用一个。单独实现一个并不难,因为框架没有提供任何实现 Woops,.Take()不会这么做
下面是.TakeLast()的一个实现
您可以在每次添加后删除(0)(如果列表长度超过20),这样列表将永远不会超过20项。既然您提到了堆栈,我想您只需要在列表末尾进行修改 在这种情况下,列表实际上是一个很好的解决方案(缓存效率高,最后插入/删除速度快)。但是,提取最后几项的方法有些低效,因为
IEnumerable
不会公开列表提供的随机访问。因此,Skip()
-实现必须扫描整个列表,直到它到达末尾(或者首先执行运行时类型检查,以检测容器是否实现了IList
)。通过索引直接访问项目,或者(如果需要第二个数组)使用List.CopyTo()
,效率更高
如果在开始时需要快速删除/插入,您可能需要考虑环形缓冲区或(双份)链表(参见<代码>链接目录> /代码>)。链表的缓存效率较低,但从两个方向进行导航和更改很容易且高效。环形缓冲区的实现有点困难,但会更节省缓存和空间。因此,如果只存储小值类型或引用类型,可能会更好。特别是当缓冲区大小固定时。
你说的是堆栈,但你也说你只想要最后20项。我认为这两个要求并不完全一致 我想说约翰尼斯关于环形缓冲区的观点是正确的。在.NET中自己实现这一点非常容易;只需使用队列
,一旦达到容量(20),就可以在每次排队(推)时开始排队(弹出)
如果希望PeekRange从最近到最不最近进行枚举,可以定义GetEnumerator
执行类似return\u queue.Reverse().GetEnumerator()的操作代码>