2008-09-08 12 views
8

Tengo una matriz bidimensional en la que necesito cargar datos. Sé el ancho de los datos (22 valores) pero no sé la altura (se estiman alrededor de 4000 registros, pero variable).Cómo inicializar una matriz bidimensional cuando no se conoce el tamaño

tengo que declara como sigue:

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

Esto provoca una NullReferenceException, por lo que cuando intento inicializar así:

_calibrationSet = new float[,]; 

Puedo obtener una "creación de la matriz debe tener tamaño de la matriz o inicializador de matriz. "

Gracias, Keith

Respuesta

8

No puede utilizar una matriz. O más bien, necesitaría elegir un tamaño, y si terminaba necesitando más, tendría que asignar una nueva matriz más grande, copiar los datos de la anterior en la nueva y continuar como antes (hasta que exceda el tamaño del nuevo ...)

En general, usted iría con una de las clases de colección - ArrayList, Lista <>, LinkedList <>, etc. - que depende mucho de lo que 'que estas buscando; List le dará lo más parecido a lo que describí inicialmente, mientras que LinkedList <> evitará el problema de reasignaciones frecuentes (a costa de un acceso más lento y un mayor uso de memoria).

Ejemplo:

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] 

Ah, y vale la pena señalar (como lo hicieron Grauenwolf), que lo que estoy haciendo aquí no le otorga la misma estructura de la memoria como una sola matriz, multidimensional haría - bajo el capó, es una serie de referencias a otras matrices que realmente contienen los datos. Esto acelera la construcción de la matriz en gran medida al hacer que la reasignación sea más económica, pero puede tener un impacto en la velocidad de acceso (y, por supuesto, en el uso de la memoria). Si esto es un problema para usted depende mucho de lo que hará con los datos después de que se carguen ... y de si hay doscientos registros o dos millones de registros.

2

No se puede crear una matriz en .NET (en lugar de declarar una referencia a ella, que es lo que hizo en su ejemplo) sin especificar sus dimensiones, explícita o implícitamente al especificar un conjunto de valores literales cuando lo inicializas (por ej. int [,] array4 = {{1, 2}, {3, 4}, {5, 6}, {7, 8}};)

Primero debe usar una estructura de datos de tamaño variable (una lista genérica de matrices de 1 elemento de 22 elementos sería la más simple) y luego asigne su matriz y copie sus datos en ella después de que termine su lectura y sepa cuántas filas necesita.

0

Generalmente utilizo las colecciones más agradables para este tipo de trabajo (Lista, Lista de matrices, etc.) y luego (si es realmente necesario) lo lanzo a T [,] cuando termino.

0

, debe preasignar la matriz a un Tamaño máximo (flotante [999,22]) o utilizar una estructura de datos diferente.

Creo que se puede copiar/cambiar el tamaño de sobre la marcha .. (pero no creo que te gustaría)

creo que la lista suena razonable.

1

Solo usaría una lista, luego convertiría esa lista en una matriz.

Notarás aquí que utilicé una matriz dentada (float [] []) en lugar de una matriz cuadrada (float [,]). Además de ser la forma "estándar" de hacer las cosas, debería ser mucho más rápido. Al convertir los datos de una lista a una matriz, solo tiene que copiar punteros [calibrationRow]. Usando una matriz cuadrada, tendría que copiar flotantes [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(); 
0

También es posible usar un ArrayList de dos dimensiones (de System.Collections) - se crea un ArrayList, a continuación, poner otro ArrayList en su interior. Esto le dará el cambio de tamaño dinámico que necesita, pero a expensas de un poco de sobrecarga.

+0

Un poco de sobrecarga, en realidad: ArrayList() encajona los flotadores, que serán lentos y requerirán mucha memoria ... –

Cuestiones relacionadas