代码之家  ›  专栏  ›  技术社区  ›  Keith Sirmons

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

  •  8
  • Keith Sirmons  · 技术社区  · 16 年前

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

    我得到一个“数组创建必须有数组大小或数组初始值设定项。”

    谢谢您, 基思

    6 回复  |  直到 14 年前
        1
  •  8
  •   Community CDub    8 年前

    不能使用数组。 或者更确切地说,您需要选择一个大小,如果您最终需要更多,那么您需要分配一个新的、更大的数组,将数据从旧数组复制到新数组中,并像以前一样继续(直到您超过新数组的大小…)

    通常,您会选择一个集合类—arraylist、list<gt;、linkedlist<gt;等—这一类很大程度上取决于您要查找的内容;list将为您提供与我最初描述的内容最接近的内容,而linkedlist<gt;将避免频繁重新分配的问题(代价是访问速度较慢且更大内存使用情况。

    例子:

    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
  •  2
  •   McKenzieG1    16 年前

    您不能在.NET中创建数组(而不是声明对它的引用,这是您在示例中所做的),而不在初始化它时显式或隐式地指定一组文本值来指定它的维度。(例如int[,]array4=1,2,3,4,5,6,7,8)

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

        3
  •  1
  •   Jonathan Allen    16 年前

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

    这里您会注意到我使用了交错数组(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();
    
        4
  •  0
  •   Daren Thomas    16 年前

    我通常将更好的集合用于这类工作(list、arraylist等),然后(如果确实需要)在完成后强制转换为t[,]。

        5
  •  0
  •   ShoeLace    16 年前

    您要么需要将数组预分配到最大大小(float[999,22]),要么使用不同的数据结构。

    我想你可以快速复制/调整大小。(但我认为你不想)

    我觉得这个清单听起来很合理。

        6
  •  0
  •   Guy Starbuck    16 年前

    也可以使用二维数组列表(来自System.Collections)——创建一个数组列表,然后在其中放置另一个数组列表。这将为您提供所需的动态调整,但要花费一些开销。