Как вы инициализируете 2-мерный массив, когда вы не знаете размер - PullRequest
8 голосов
/ 09 сентября 2008

У меня есть двумерный массив, в который мне нужно загрузить данные. Я знаю ширину данных (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 голосов
/ 09 сентября 2008

Вы не можете использовать массив. Или, скорее, вам нужно будет выбрать размер, и если вам понадобится больше, вам придется выделить новый, больший массив, скопировать данные из старого в новый и продолжить как раньше (до Вы превышаете размер нового ...)

Как правило, вы должны использовать один из классов коллекции - 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 голосов
/ 09 сентября 2008

Вы не можете создать массив в .NET (в отличие от объявления ссылки на него, что вы и сделали в вашем примере) без указания его размеров, явно или неявно, указав набор литеральных значений, когда Вы инициализируете это. (например, int [,] array4 = {{1, 2}, {3, 4}, {5, 6}, {7, 8}};)

Сначала необходимо использовать структуру данных переменного размера (общий список из 22-элементных 1-мерных массивов будет самым простым), а затем выделить массив и скопировать в него данные после завершения чтения, и вы знаете, сколько строк вам нужно.

1 голос
/ 09 сентября 2008

Я бы просто использовал список, а затем преобразовал бы этот список в массив.

Здесь вы заметите, что я использовал зубчатый массив (float [] []) вместо квадратного массива (float [,]). Помимо того, что это «стандартный» способ ведения дел, он должен быть намного быстрее. При преобразовании данных из списка в массив вам нужно только скопировать указатели [calibRow]. Используя квадратный массив, вам нужно будет скопировать [calibRow] x [SensorCount] float.

        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 голосов
/ 09 сентября 2008

Вы также можете использовать двумерный ArrayList (из System.Collections) - вы создаете ArrayList, а затем помещаете в него другой ArrayList. Это даст вам необходимое динамическое изменение размера, но за счет небольшого количества накладных расходов.

0 голосов
/ 09 сентября 2008

вам необходимо либо предварительно выделить массив для максимального размера (float [999,22]), либо использовать другую структуру данных.

Я думаю, вы можете скопировать / изменить размер на лету .. (но я не думаю, что вы захотите)

Я думаю, что Список звучит разумно.

0 голосов
/ 09 сентября 2008

Я обычно использую более приятные коллекции для такого рода работы (List, ArrayList и т. Д.), А затем (если это действительно необходимо) приведу к T [,], когда я закончу.

...