Как вы инициализируете двумерный массив, когда вы не знаете размер
У меня есть двумерный массив, в который мне нужно загрузить данные. Я знаю ширину данных (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 ответов
Вы не можете использовать массив. Или, скорее, вам нужно будет выбрать размер, и если вам понадобится больше, вам придется выделить новый, больший массив, скопировать данные из старого в новый и продолжить как раньше (до тех пор, пока Вы превышаете размер нового...)
Как правило, вы должны использовать один из классов коллекции - 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]
О, и стоит отметить (как это сделал Грауэнольф), что то, что я делаю здесь, не дает вам ту же структуру памяти, что и один многомерный массив - под капотом, это массив ссылок на другие массивы которые на самом деле содержат данные. Это ускоряет построение массива за счет удешевления перераспределения, но может повлиять на скорость доступа (и, конечно, на использование памяти). Является ли это проблемой для вас, во многом зависит от того, что вы будете делать с данными после их загрузки... и от того, есть ли двести записей или два миллиона записей.
Вы не можете создать массив в.NET (в отличие от объявления ссылки на него, что вы и сделали в вашем примере), не указав его размеры, явно или неявно, указав набор литеральных значений при его инициализации., (например, int[,] array4 = { { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 } };)
Сначала необходимо использовать структуру данных переменного размера (общий список из 22-элементных 1-d массивов будет самым простым), а затем выделить свой массив и скопировать в него данные после завершения чтения и определения количества строк. тебе нужно.
Я бы просто использовал список, а затем преобразовал бы этот список в массив.
Здесь вы заметите, что я использовал зубчатый массив (float [] []) вместо квадратного массива (float [,]). Помимо того, что это "стандартный" способ ведения дел, он должен быть намного быстрее. При преобразовании данных из списка в массив вам нужно только скопировать указатели [calibRow]. Используя квадратный массив, вам нужно будет скопировать значения [calibRow] 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. Это даст вам динамическое изменение размера, в котором вы нуждаетесь, но за счет небольших накладных расходов.
Вам нужно будет либо предварительно выделить массив для максимального размера (float[999,22]), либо использовать другую структуру данных.
Я думаю, вы можете скопировать / изменить размер на лету.. (но я не думаю, что вы захотите)
Я думаю, что Список звучит разумно.
Я обычно использую более приятные коллекции для такого рода работы (List, ArrayList и т. Д.), А затем (если это действительно необходимо) приведу к T[,], когда я закончу.