2010-11-25 143 views
0

我有一个程序需要存储数据值并定期获取最后的'x'数据值。PeekRange在C#堆栈中?

它最初认为堆栈是要走的路,但我需要能够看到的不仅仅是最高值 - 就像PeekRange方法一样,我可以在其中查看最后的'x'个值。

目前我只是使用列表,并获得最后说,20个值是这样的:

var last20 = myList.Skip(myList.Count - 20).ToList(); 

的名单不断增加的所有程序运行的时候,但我只想要过的最后一个20个值。有人可以就更好的数据结构提供一些建议吗?

回答

1

既然你提到了堆栈,我想你只需要在列表末尾进行修改?

在这种情况下,该列表实际上是一个很好的解决方案(缓存高效并且在最后快速插入/移除)。但是,提取最后几项的方法效率不高,因为IEnumerable<T>不会公开由列表提供的随机访问。因此,实现必须扫描整个列表直到到达结尾(或者首先执行运行时类型检查以检测容器实现的IList<T>)。更直接地通过索引访问项目,或者(如果您需要第二个阵列)使用List<T>.CopyTo()更高效。

如果您在开始时需要快速移除/插入,您可能需要考虑环形缓冲区或(双向)链接列表(请参阅LinkedList<T>)。链接列表的缓存效率会更低,但从两个方向进行导航和更改都很容易且高效。环形缓冲区实施起来有点困难,但会更具缓存和空间效率。所以如果只存储小值类型或引用类型,它可能会更好。特别是当缓冲区大小固定时。

4

我可能会使用ring buffer。它不是很难自己实现,AFAIK没有框架提供的实现。

1

你可以只RemoveAt移除(0)后,每增加(如果该列表的长度超过20),因此该列表决不会超过20项目。

1

你说的堆栈,但你也说过你只想过去的20个项目。我不认为这两个要求真的一起。

我会说约翰尼斯是正确的环缓冲区。这很容易在.NET中自己实现;只需使用一个Queue<T>,一旦你达到你的容量(20),开始出队(弹出)每个入队(推)。

如果你希望你的PeekRange从最近的枚举至少近,你可以定义GetEnumerator做somehing像return _queue.Reverse().GetEnumerator();