Как вы инициализируете двумерный массив, если вы не знаете его размер

StackOverflow https://stackoverflow.com/questions/50558

  •  09-06-2019
  •  | 
  •  

Вопрос

У меня есть двумерный массив, в который мне нужно загрузить данные.Я знаю ширину данных (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<>, Список ссылок<> и т.д.- какой из них во многом зависит от того, что вы ищете;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 did), что то, что я здесь делаю, не дает вам той же структуры памяти, что и единый многомерный массив - по сути, это массив ссылок на другие массивы, которые фактически содержат данные.Это значительно ускоряет построение массива за счет удешевления перераспределения, но может повлиять на скорость доступа (и, конечно, на использование памяти).Является ли это проблемой для вас, во многом зависит от того, что вы будете делать с данными после их загрузки...и независимо от того, есть ли двести записей или два миллиона записей.

Другие советы

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

Сначала вам нужно использовать структуру данных переменного размера (общий список из 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();

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top