65.9K
CodeProject 正在变化。 阅读更多。
Home

通用循环数组

starIconstarIconstarIcon
emptyStarIcon
starIcon
emptyStarIcon

3.21/5 (6投票s)

2008年12月10日

CPOL

2分钟阅读

viewsIcon

67850

downloadIcon

822

一个高效的循环数组 - 固定长度的先入先出。

引言

CircularArray<T> 是一个实现固定长度的先入后出 '队列' 或缓冲区的类。这很有用,例如,如果您想保留实时系统中的最后 30 个值。下一个值被放入数组中,然后数组中的最后一个值被推出。它通过使用固定数组来实现这一点,并使用 DivRem 数学运算符来计算数组中头部和尾部的位置。它就像一个循环数组,指针在圆圈中移动。唯一的缺点是我必须使用一个内部 facade 数组来以我想要的顺序获取一个数组,并复制出这些值;显然,这并不理想。我没有想到其他办法,除非我决定实现看起来像数组但实际上是链表之类的东西。

背景

我需要在一个实时股票跟踪应用程序中高效地保留最后 X 个值,以便计算各种东西。我没有在泛型中找到任何类似的东西(我可能错了。如果我错了,请有人告诉我是否有可用的内置类)。

使用代码

构造函数指定要容纳的元素数量。在这里,我容纳 'Bar' 对象

CircularArray<Bar> _circularArray = new CircularArray<Bar>(periods);

使用 Push 方法将一个值推入数组

_circularArray.Push(value);

Get 方法从头部获取元素 X,例如,Get(0) 获取您推入的最后一个值,Get(1) 获取您推入的倒数第二个值等等。

_circularArray.Get(i)

Array 方法返回一个从尾到头的数组,例如,从最早的值到推入队列的最新值。这的一个用途可能是将其用作 TA-LIB 技术分析库的输入,或任何您需要在实时系统中获取最后 X 个值的数组的地方。这是 Array 的单元测试片段。

[Test]

public void Push()
{

    CircularArray<int> cq = new CircularArray<int>(5);

    cq.Push(1);
    cq.Push(2);
    cq.Push(3);
    cq.Push(4);
    cq.Push(5);
    cq.Push(6);
    cq.Push(7);
    cq.Push(8);
    cq.Push(9);
    cq.Push(10);
    cq.Push(11);

    Assert.AreEqual(7, cq.Array[0]);
    Assert.AreEqual(8, cq.Array[1]);
    Assert.AreEqual(9, cq.Array[2]);
    Assert.AreEqual(10, cq.Array[3]);
    Assert.AreEqual(11, cq.Array[4]);

}

我已经将代码和单元测试包含在解决方案的 Zip 文件中;一切都在那里。

关注点

如前所述,我找不到任何已经提供这种功能的东西。我可能错过了一些内置的泛型 Microsoft 类。如果有人知道这种东西,请告诉我!

更新:请注意,在我发布这篇文章后,我确实阅读了 Marc Clifton 的文章 '循环列表'。在将其插入一个与上述内容等效的 NUnit 测试中之后

[Test]
public void CicularList()
{

    CircularList<int> cq = new CircularList<int>(5);

    cq.Value = 1;
    cq.Next();

    cq.Value = 2;
    cq.Next();

    cq.Value = 3;
    cq.Next();

    cq.Value = 4;
    cq.Next();

    cq.Value = 5;
    cq.Next();

    cq.Value = 6;
    cq.Next();

    cq.Value = 7;
    cq.Next();

    cq.Value = 8;
    cq.Next();

    cq.Value = 9;
    cq.Next();

    cq.Value = 10;
    cq.Next();

    cq.Value = 11;
    cq.Next();

    Assert.AreEqual(7, cq[0]); // Failed its 11
    Assert.AreEqual(8, cq[1]); // Failed its 7
    Assert.AreEqual(9, cq[2]); // Failed its 8
    Assert.AreEqual(10, cq[3]); // Failed its 9
    Assert.AreEqual(11, cq[4]); // Failed its 10

}

数组 cq 将是 11,7,8,9,10,这是原始循环数组。我期望的是 7,8,9,10,11 - 例如,最后 5 个值,从最早到最新。也许,我用错了。上面“失败”只是与我期望的相悖,所以不要过度解读。我相信 CircularList 对某些人来说很有用,只是不适用于我的目的。我完全尊重和重视 Marc Clifton 的贡献。

© . All rights reserved.