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

时间:2021-11-20 21:29:48

I have a two dimensional array that I need to load data into. I know the width of the data (22 values) but I do not know the height (estimated around 4000 records, but variable).

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

I have it declared as follows:

我声明如下:

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

This causes a NullReferenceException, so when I try to initialize it like this:

这会导致NullReferenceException,所以当我尝试像这样初始化它时:

_calibrationSet = new float[,];

I get an "Array creation must have array size or array initializer."

我得到一个“数组创建必须有数组大小或数组初始化程序。”

Thank you, Keith

谢谢,基思

6 个解决方案

#1


8  

You can't use an array. Or rather, you would need to pick a size, and if you ended up needing more then you would have to allocate a new, larger, array, copy the data from the old one into the new one, and continue on as before (until you exceed the size of the new one...)

你不能使用数组。或者更确切地说,您需要选择一个大小,如果您最终需要更多,那么您将不得不分配一个新的更大的数组,将旧数据中的数据复制到新数组中,然后继续执行(直到你超过新的大小......)

Generally, you would go with one of the collection classes - ArrayList, List<>, LinkedList<>, etc. - which one depends a lot on what you're looking for; List will give you the closest thing to what i described initially, while LinkedList<> will avoid the problem of frequent re-allocations (at the cost of slower access and greater memory usage).

通常,您可以使用其中一个集合类 - ArrayList,List <>,LinkedList <>等 - 这取决于您正在寻找的内容; List将为您提供最接近我最初描述的内容,而LinkedList <>将避免频繁重新分配的问题(以较慢的访问和更大的内存使用为代价)。

Example:

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]

Oh, and it's worth noting (as Grauenwolf did), that what i'm doing here doesn't give you the same memory structure as a single, multi-dimensional array would - under the hood, it's an array of references to other arrays that actually hold the data. This speeds up building the array a good deal by making reallocation cheaper, but can have an impact on access speed (and, of course, memory usage). Whether this is an issue for you depends a lot on what you'll be doing with the data after it's loaded... and whether there are two hundred records or two million records.

哦,值得注意的是(正如Grauenwolf所做的那样),我在这里所做的并没有给你提供与单个多维数组相同的内存结构 - 在引擎盖下,它是对其他数组的引用数组实际上持有数据。通过使重新分配更便宜,这可以加快构建阵列的速度,但是可以对访问速度(当然还有内存使用)产生影响。这对您来说是否是一个问题,很大程度上取决于您在加载数据后将对数据进行的操作......以及是否有200条记录或200万条记录。

#2


2  

You can't create an array in .NET (as opposed to declaring a reference to it, which is what you did in your example) without specifying its dimensions, either explicitly, or implicitly by specifying a set of literal values when you initialize it. (e.g. int[,] array4 = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };)

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

You need to use a variable-size data structure first (a generic list of 22-element 1-d arrays would be the simplest) and then allocate your array and copy your data into it after your read is finished and you know how many rows you need.

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

#3


1  

I would just use a list, then convert that list into an array.

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

You will notice here that I used a jagged array (float[][]) instead of a square array (float [,]). Besides being the "standard" way of doing things, it should be much faster. When converting the data from a list to an array you only have to copy [calibrationRow] pointers. Using a square array, you would have to copy [calibrationRow] x [SensorCount] floats.

你会注意到我使用了锯齿状数组(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  

I generally use the nicer collections for this sort of work (List, ArrayList etc.) and then (if really necessary) cast to T[,] when I'm done.

我通常使用更好的集合进行这种工作(List,ArrayList等),然后(如果真的有必要)在我完成时转换为T [,]。

#5


0  

you would either need to preallocate the array to a Maximum size (float[999,22] ) , or use a different data structure.

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

i guess you could copy/resize on the fly.. (but i don't think you'd want to)

我想你可以在飞行中复制/调整大小..(但我认为你不想)

i think the List sounds reasonable.

我觉得名单听起来很合理。

#6


0  

You could also use a two-dimensional ArrayList (from System.Collections) -- you create an ArrayList, then put another ArrayList inside it. This will give you the dynamic resizing you need, but at the expense of a bit of overhead.

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

#1


8  

You can't use an array. Or rather, you would need to pick a size, and if you ended up needing more then you would have to allocate a new, larger, array, copy the data from the old one into the new one, and continue on as before (until you exceed the size of the new one...)

你不能使用数组。或者更确切地说,您需要选择一个大小,如果您最终需要更多,那么您将不得不分配一个新的更大的数组,将旧数据中的数据复制到新数组中,然后继续执行(直到你超过新的大小......)

Generally, you would go with one of the collection classes - ArrayList, List<>, LinkedList<>, etc. - which one depends a lot on what you're looking for; List will give you the closest thing to what i described initially, while LinkedList<> will avoid the problem of frequent re-allocations (at the cost of slower access and greater memory usage).

通常,您可以使用其中一个集合类 - ArrayList,List <>,LinkedList <>等 - 这取决于您正在寻找的内容; List将为您提供最接近我最初描述的内容,而LinkedList <>将避免频繁重新分配的问题(以较慢的访问和更大的内存使用为代价)。

Example:

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]

Oh, and it's worth noting (as Grauenwolf did), that what i'm doing here doesn't give you the same memory structure as a single, multi-dimensional array would - under the hood, it's an array of references to other arrays that actually hold the data. This speeds up building the array a good deal by making reallocation cheaper, but can have an impact on access speed (and, of course, memory usage). Whether this is an issue for you depends a lot on what you'll be doing with the data after it's loaded... and whether there are two hundred records or two million records.

哦,值得注意的是(正如Grauenwolf所做的那样),我在这里所做的并没有给你提供与单个多维数组相同的内存结构 - 在引擎盖下,它是对其他数组的引用数组实际上持有数据。通过使重新分配更便宜,这可以加快构建阵列的速度,但是可以对访问速度(当然还有内存使用)产生影响。这对您来说是否是一个问题,很大程度上取决于您在加载数据后将对数据进行的操作......以及是否有200条记录或200万条记录。

#2


2  

You can't create an array in .NET (as opposed to declaring a reference to it, which is what you did in your example) without specifying its dimensions, either explicitly, or implicitly by specifying a set of literal values when you initialize it. (e.g. int[,] array4 = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };)

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

You need to use a variable-size data structure first (a generic list of 22-element 1-d arrays would be the simplest) and then allocate your array and copy your data into it after your read is finished and you know how many rows you need.

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

#3


1  

I would just use a list, then convert that list into an array.

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

You will notice here that I used a jagged array (float[][]) instead of a square array (float [,]). Besides being the "standard" way of doing things, it should be much faster. When converting the data from a list to an array you only have to copy [calibrationRow] pointers. Using a square array, you would have to copy [calibrationRow] x [SensorCount] floats.

你会注意到我使用了锯齿状数组(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  

I generally use the nicer collections for this sort of work (List, ArrayList etc.) and then (if really necessary) cast to T[,] when I'm done.

我通常使用更好的集合进行这种工作(List,ArrayList等),然后(如果真的有必要)在我完成时转换为T [,]。

#5


0  

you would either need to preallocate the array to a Maximum size (float[999,22] ) , or use a different data structure.

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

i guess you could copy/resize on the fly.. (but i don't think you'd want to)

我想你可以在飞行中复制/调整大小..(但我认为你不想)

i think the List sounds reasonable.

我觉得名单听起来很合理。

#6


0  

You could also use a two-dimensional ArrayList (from System.Collections) -- you create an ArrayList, then put another ArrayList inside it. This will give you the dynamic resizing you need, but at the expense of a bit of overhead.

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