Comment initialiser un tableau à 2 dimensions dont on ne connaît pas la taille

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

  •  09-06-2019
  •  | 
  •  

Question

J'ai un tableau à deux dimensions dans lequel je dois 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).

Je l'ai déclaré ainsi :

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 quand j'essaie de l'initialiser comme ceci :

_calibrationSet = new float[,];

J'obtiens un message "La création d'un tableau doit avoir une taille de tableau ou un initialiseur de tableau".

Merci, Keith

Était-ce utile?

La solution

Vous ne pouvez pas utiliser de tableau.Ou plutôt, vous devrez choisir une taille, et si vous en avez besoin de plus, 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épassez la taille du nouveau...)

Généralement, vous utiliserez l'une des classes de collection - ArrayList, List<>, LinkedList<>, etc.- lequel dépend beaucoup de ce que vous recherchez ;List vous donnera la chose la plus proche de ce que j'ai décrit initialement, tandis que LinkedList<> évitera le problème des réallocations fréquentes (au prix d'un accès plus lent et d'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 ça vaut la peine de le noter (comme Loup gris fait), que ce que je fais ici ne vous donne pas la même structure de mémoire qu'un tableau unique et multidimensionnel - 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 de la baie en rendant la réallocation 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.

Autres conseils

Vous ne pouvez pas créer un tableau dans .NET (au lieu de déclarer une référence à celui-ci, comme vous l'avez fait dans votre exemple) sans spécifier ses dimensions, soit explicitement, soit 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 1D de 22 éléments serait la plus simple), puis allouer votre tableau et y copier vos données une fois votre lecture terminée et vous savez combien de lignes vous avez besoin.

J'utiliserais simplement une liste, puis convertirais cette liste en tableau.

Vous remarquerez ici que j'ai utilisé un tableau irrégulier (float[][]) au lieu d'un tableau carré (float [,]).En plus d'être la manière « standard » de faire les choses, cela devrait être beaucoup plus rapide.Lors de la conversion des données d'une liste en tableau, il vous suffit de copier les pointeurs [calibrationRow].En utilisant un tableau carré, vous devrez copier les flotteurs [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();

J'utilise généralement les plus belles collections pour ce type de travail (List, ArrayList, etc.), puis (si vraiment nécessaire) je les convertis en T[,] lorsque j'ai terminé.

vous devrez 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 tu le voudrais)

je pense que la liste semble raisonnable.

Vous pouvez également utiliser une ArrayList bidimensionnelle (à partir de System.Collections) : vous créez une ArrayList, puis y insérez une autre ArrayList.Cela vous donnera le redimensionnement dynamique dont vous avez besoin, mais au prix d'un peu de surcharge.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top