不知道大小时如何初始化二维数组

时间:2020-03-05 18:49:37  来源:igfitidea点击:

我有一个二维数组,需要将数据加载到其中。我知道数据的宽度(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[,];

我得到"数组创建必须具有数组大小或者数组初始化程序"。

谢谢,
基思

解决方案

回答

我们不能使用数组。
或者更确切地说,我们将需要选择一个大小,如果最终需要更多的大小,则必须分配一个新的更大的数组,将数据从旧的复制到新的,然后像以前一样继续操作(直到我们超出了新的尺寸...)

通常,我们将使用ArrayList,List <>,LinkedList <>等集合类之一,该类在很大程度上取决于我们要查找的内容。列表将为我们提供与我最初描述的最接近的东西,而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所做的那样),我在这里所做的并没有为我们提供与单个多维数组在幕后相同的内存结构,而是其他数组的引用数组实际保存数据。这样可以通过降低重新分配的成本来加快阵列的构建速度,但会影响访问速度(当然还有内存使用)。这对我们来说是否是一个问题,很大程度上取决于数据加载后的处理方式……以及是否有200条记录或者200万条记录。

回答

我们不能在.NET中创建数组(而不是声明对它的引用,这是我们在示例中所做的事情),而无需在初始化时通过指定一组文字值来显式或者隐式地指定其尺寸。 (例如int [,] array4 = {{{1,2},{3,4},{5,6},{7,8}};)

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

回答

通常,我会使用更好的集合来进行此类工作(List,ArrayList等),然后(如果确实需要)在完成后转换为T [,]。

回答

我们可能需要将数组预分配为最大大小(float [999,22]),或者使用其他数据结构。

我想我们可以即时复制/调整大小。(但我不认为我们愿意)

我认为这份清单听起来很合理。

回答

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

我们会在这里注意到,我使用了锯齿状数组(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();

回答

我们还可以使用二维ArrayList(来自System.Collections)-创建一个ArrayList,然后在其中放入另一个ArrayList。这将为我们提供所需的动态调整大小,但以一些开销为代价。