2008-09-08 6 views
8

J'ai un tableau bidimensionnel dont j'ai besoin pour charger des données. Je connais la largeur des données (22 valeurs) mais je ne connais pas la hauteur (estimée à environ 4000 enregistrements, mais variable).Comment initialiser un tableau bidimensionnel lorsque vous ne connaissez pas la taille

je l'ai déclaré comme suit:

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

Cela provoque une NullReferenceException, donc lorsque je tente de l'initialiser comme ceci:

_calibrationSet = new float[,]; 

-je obtenir une « création Array doit avoir la taille du tableau ou initialiseur de tableau. "

Merci, Keith

Répondre

8

Vous ne pouvez pas utiliser un tableau. Ou plutôt, vous auriez besoin de choisir une taille, et si vous avez besoin de plus, alors vous devrez allouer un nouveau tableau plus grand, copier les données de l'ancien dans le nouveau, et continuer comme avant (jusqu'à ce que vous dépassiez la taille du nouveau ...)

Généralement, vous iriez avec l'une des classes de collection - ArrayList, Liste <>, LinkedList <>, etc - qui dépend beaucoup de ce que vous cherchons; Liste vous donnera la chose la plus proche de ce que j'ai décrit initialement, tandis que LinkedList <> permettra d'éviter le problème des réallocations fréquentes (au prix d'un accès plus lent et une plus grande utilisation de la mémoire).

Exemple:

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, et il est intéressant de noter (comme Grauenwolf a fait), que ce que je fais ici ne vous donne pas la même structure de mémoire comme une seule, un tableau multidimensionnel serait - sous le capot, c'est un tableau de références à d'autres tableaux qui contiennent réellement les données. Cela accélère considérablement la construction du réseau en rendant la réaffectation moins coûteuse, mais peut avoir un impact sur la vitesse d'accès (et, bien sûr, sur l'utilisation de la mémoire). Que ce soit un problème pour vous dépend beaucoup de ce que vous ferez avec les données après leur chargement ... et s'il y a deux cents enregistrements ou deux millions d'enregistrements.

2

Vous ne pouvez pas créer un tableau dans .NET (par opposition à la déclaration d'une référence, ce que vous avez fait dans votre exemple) sans spécifier ses dimensions, explicitement ou implicitement, en spécifiant un ensemble de valeurs littérales lorsque vous l'initialisez. (par exemple int [,] array4 = {{1, 2}, {3, 4}, {5, 6}, {7, 8}};)

Vous devez d'abord utiliser une structure de données de taille variable (une liste générique de tableaux de 1 élément de 22 éléments serait la plus simple), puis allouer votre tableau et y copier vos données après que votre lecture est terminée et vous savez combien de lignes vous avez besoin.

0

J'utilise généralement les plus belles collections pour ce genre de travail (List, ArrayList etc.) et ensuite (si vraiment nécessaire) cast à T [,] quand j'ai terminé.

0

vous devez soit préallouer le tableau à une taille maximale (float [999,22]), soit utiliser une structure de données différente.

Je suppose que vous pouvez copier/redimensionner à la volée .. (mais je ne pense pas que vous voulez)

Je pense que la liste semble raisonnable.

1

Je voudrais simplement utiliser une liste, puis convertir cette liste en tableau.

Vous remarquerez ici que j'ai utilisé un tableau en dents de scie (float [] []) au lieu d'un tableau carré (float [,]). En plus d'être la façon «standard» de faire les choses, cela devrait être beaucoup plus rapide. Lors de la conversion des données d'une liste en tableau, il suffit de copier les pointeurs [calibrationRow]. En utilisant une matrice carrée, vous devez copier [floatRow] x [SensorCount] flottants.

 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

Vous pouvez également utiliser un ArrayList en deux dimensions (à partir System.Collections) - vous créez un ArrayList, puis mettre une autre ArrayList à l'intérieur. Cela vous donnera le redimensionnement dynamique dont vous avez besoin, mais au détriment d'un peu de frais généraux.

+0

Un peu de surcharge, en fait: ArrayList() va encadrer les flottants, ce qui sera lent et la mémoire intensive ... –

Questions connexes