当你不知道大小时,如何初始化一个二维数组?

8

我有一个二维数组需要加载数据。我知道数据的宽度(22个值),但是我不知道高度(大约估计为4000个记录,但是可变)。

我已经声明如下:

float[,] _calibrationSet;
    ....
int calibrationRow = 0;
While (recordsToRead)
{
  for (int i = 0; i < SensorCount; i++)
   {
     _calibrationSet[calibrationRow, i] = calibrationArrayView.ReadFloat();
   }
   calibrationRow++;
}

这会导致NullReferenceException异常,因此当我尝试像这样初始化它时:
_calibrationSet = new float[,];

我收到一个"数组创建必须具有数组大小或数组初始化程序"的错误信息。

谢谢, Keith

6个回答

8
你不能使用数组。或者说,你需要选择一个大小,如果最终需要更多的空间,那么你就需要分配一个新的、更大的数组,将数据从旧数组复制到新数组中,并像之前一样继续操作(直到超出新数组的大小...)。
通常情况下,你会选择其中一个集合类——ArrayList、List<>、LinkedList<>等,具体选择取决于你想要什么;List会给你最接近我最初描述的东西,而LinkedList<>则避免了频繁重新分配的问题(代价是访问速度较慢和内存使用量更大)。
示例:
List<float[]> _calibrationSet = new List<float[]>();

// ...

while (recordsToRead)
{
    float[] record = new float[SensorCount];
    for (int i = 0; i < SensorCount; i++)
    {
        record[i] = calibrationArrayView.ReadFloat();
    }
    _calibrationSet.Add(record);
}

// access later: _calibrationSet[record][sensor]

值得注意的是(如Grauenwolf所说),我在这里所做的并不会给你一个与单个多维数组相同的内存结构 - 在底层,它是一个指向实际保存数据的其他数组的引用数组。这通过使重新分配更加便宜来加速数组的构建,但可能会对访问速度(以及内存使用)产生影响。这是否对您有影响取决于加载数据后您将要做什么...以及记录数是两百还是两百万。


2

在.NET中,你无法创建一个数组(与你在示例中声明引用不同),除非显式地指定其维度,或者通过在初始化时指定一组文字值隐式地指定它的维度。(例如,int[,] array4 = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };)

您需要先使用一个可变大小的数据结构(一个包含22个元素的1D数组的通用列表将是最简单的),然后在读取完成并且您知道需要多少行之后分配您的数组并将数据复制到其中。


1

我会使用列表,然后将该列表转换为数组。

您会注意到我在这里使用了一个交错数组(float [] []),而不是一个方形数组(float [,])。除了是做事情的“标准”方式之外,它应该更快。将数据从列表转换为数组时,您只需要复制[calibrationRow]个指针。如果使用方形数组,则必须复制[calibrationRow] x [SensorCount]个浮点数。

        var tempCalibrationSet = new List<float[]>();
        const int SensorCount = 22;
        int calibrationRow = 0;

        while (recordsToRead())
        {
            tempCalibrationSet[calibrationRow] = new float[SensorCount];

            for (int i = 0; i < SensorCount; i++)
            {
                tempCalibrationSet[calibrationRow][i] = calibrationArrayView.ReadFloat();
            } calibrationRow++;
        }

        float[][] _calibrationSet = tempCalibrationSet.ToArray();

0
我通常在这种情况下使用更好的集合(List、ArrayList 等),然后在完成操作时(如果真的必要)将其转换为 T[,]。

0

你需要预先分配数组的最大大小(float[999,22]),或使用不同的数据结构。

我猜你可以动态复制/调整大小..(但我认为你不想这样做)

我认为列表听起来很合理。


0
你也可以使用二维ArrayList(来自System.Collections)--创建一个ArrayList,然后在其中放置另一个ArrayList。这将为您提供所需的动态调整大小,但会牺牲一些开销。

实际上有相当多的开销:ArrayList()会将浮点数装箱,这会导致速度变慢和内存占用增加... - Jeremy McGee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接