0

我有一个包含一百万个元素的数组,我将通过将当前索引设置为“现在”并将其递增以模拟新数据的输入,将其模拟为实时数据。

我将对现在的数据和过去的数据 X 条进行大量计算。

我想知道是否有一种方便的方法可以将其抽象为在 someDataType[0] 和 1 bar 之前访问今天的数据,如 someDataType[1] 等等?

我是编程新手,所以我不确定什么是可能的,什么是不可能的。理想情况下,这种数据类型不必将数据从数组复制到数据类型,而是可以存储所有数据本身并跳过数组或以某种方式指向数组。它肯定必须能够以与数组相同的方式访问数据,而不必像列表那样遍历自身以达到某个点。

我真的不知道这是否可能以任何方式、形状或形式出现。所以我问。感谢您的任何意见!:)

4

3 回答 3

4

首先,如果您想添加新项目,那么直接使用数组可能不是最佳选择(除非最新项目应该覆盖最旧项目)。更好的选择是List<T>.

现在,您要创建的是一个“反转”集合:它将包含一个List<T>和:

  • 它的索引器将访问后备列表中的反向索引
  • 它的 add 方法(可能被调用AddFirst())将添加到列表的末尾
  • 它的GetEnumerator()方法将返回反向枚举

随着所有这些要求的充实,代码几乎可以自己编写:

class AddFirstList<T> : IEnumerable<T>, IReadOnlyList<T>
{
    private readonly List<T> m_list = new List<T>();

    public void AddFirst(T item)
    {
        m_list.Add(item);
    }

    public IEnumerator<T> GetEnumerator()
    {
        return Enumerable.Reverse(m_list).GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }

    public int Count
    {
        get { return m_list.Count; }
    }

    public T this[int index]
    {
        get { return m_list[Count - index - 1]; }
    }
}

(如果您不在 .Net 4.5 上,请删除该IReadOnlyList<T>接口。)

于 2013-02-15T00:46:18.210 回答
0

听起来您需要对结构进行动态调整大小,因此可以List<T>在 System.Collections.Generic 命名空间中找到一个不错的选择。

var list = new List<int>();
list.Add(1); // keep adding

它像数组一样提供索引访问,但您可以根据需要继续添加元素。如果您想要做的只是快速检索最后一个元素(除了通过索引进行正常随机访问之外),您可以使用针对接口优化Last()的扩展方法(并且是实现的)直接返回最后一个元素元素,而无需枚举整个序列。IList<T>List<T>

但是,听起来您想要更类似于完全反向索引访问的东西。为此,您可能必须对其进行编码。为了可重用性,您可以将其作为项目中的扩展方法,并在您需要的任何地方使用它。像这样的东西应该适合你的需要。

public static class ListExtensions
{
    public static T FromEnd<T>(this IList<T> list, int position)
    {
        if (list == null || list.Count == 0)
        {
            throw new ArgumentException("list cannot be null or empty");
        }

        return list[(list.Count - 1) - position];
    }
}

而且使用起来很简单。

var myList = new List<int>() { 1, 2, 3, 4, 5 };
int item = myList.FromEnd(1);
Debug.Assert(item == 4);

当然,这里的问题是,如果你想在 a 中循环它,这并不适合foreach(你仍然可以使用标准for)。如果使用 foreach,您可以简单地循环使用foreach (var item in myList.Reverse()) { },或者您可以使用 svick 的答案中编码的方法。

于 2013-02-15T00:45:40.557 回答
0

听起来您希望索引 0 是“当前数据”,而索引 1 是以前的数据。

您可以通过编写自己的封装百万元​​素数组的类来实现这一点。然后您可以指定索引right now并将其添加到每个索引中。例如:

public class DataArray
{
    readonly Object[] data;

    int rightNow;
    public int RightNow
    {
        get { return this.rightNow; }
        set { this.rightNow = value; }
    }

    public DataArrat(Object[] data)
    {
        // TODO: Check that data is not null.
        this.data = data;
    }

    // This is called an 'indexer':
    public Object this[int index]
    {
        get
        {
            // TODO: Check whether (index + this.rightNow) is in the valid range.
            return this.data[index + this.rightNow];
        }
    }
}

现在您可以像这样使用它,例如:

// Initialize the DataArray:
Object[] millionElementArray /* = from somewhere, e.g. */ = new []
{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
var data = new DataArray(millionElementArray);

// Start at bar 8:
data.RightNow = 8;

// Use the data:
Object currentData = data[0];
Object futureData = data[-1];
Object pastData = data[1];

// Go to the next bar:
data.RightNow--;

// Use the data:
Object currentData = data[0];
Object futureData = data[-1];
Object pastData = data[1];

// Rinse and repeat...

请注意,您应该替换Object为您正在使用的数据类型,或者使类通用。

于 2013-02-15T00:55:36.433 回答